【Python】DataFrame学习02_聚合与分组、透视表、大数据预处理技术

本人依据上课学习内容,将dataframe内容浓缩为代码块,一下是今天学习的第二部分:
1.dataframe聚合函数与分组
2.dataframe透视表
数据预处理技术:
3.数据集成(合并)
4.数据清洗
5.数据归约(标准化)
6.数据转换

本文于2021/12/13首发于csdn,如有错误和不足请指出。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

rs = pd.read_csv(r".\tmp\rs.csv", encoding='gbk')
print(rs)
'''1.聚合函数与分组'''
# (1)聚合:将多种数据按照某种方式聚合为一个标量
# 如果函数来自第三方或自定义,直接给出函数名,不要写出参数的括号
# 有些数据没有max,min,要注意
agg1 = rs["薪水"].agg(['min', 'max'])
# 薪水和小时报酬的min, median
agg2 = rs[['薪水', '小时报酬']].agg(['min', np.median])
# 看薪水的max,min,小时报酬的maen, median
agg3 = rs.agg({'薪水': ["max", "min"], '小时报酬': ["mean", "median"]})
agg4 = rs.agg({'薪水': np.min, '小时报酬': ['mean', 'median']})

# (2)分组
groupby1 = rs.groupby(['分公司']).mean()  # 返回dataframe对象,只显示了可以统计的部分
# groupby1 = rs.groupby("分公司").mean()  # 返回dataframe对象,也对
# 对分组后的列操作
groupby2 = rs.groupby(['分公司'])[['薪水']].mean()  # dataframe对象
# groupby2 = rs.groupby(["分公司"])['薪水'].mean()  # sereis对象

# (3)分组与聚合
# 按分公司分组后,小时报酬与薪水的min,max
groupby3 = rs.groupby('分公司')[['薪水', '小时报酬']].agg(["min", 'max'])

'''2.透视表'''
# index/column设置索引相当于分组,aggfunc设置聚合函数,默认为mean
# pt1 = pd.pivot_table(rs, values='小时报酬', index=['分公司'], aggfunc='min')
pt1 = rs.pivot_table(values='小时报酬', index=['分公司'], aggfunc='min')
# 多索引分组
pt2 = rs.pivot_table(values=['小时报酬', '薪水'], index=['分公司', '部门'])

'''数据预处理(清洗,集成,归约,转换)'''
'''3.数据合并(集成)'''
# (1)堆叠concat
rs1 = rs.iloc[:5, :3]
rs2 = rs.iloc[4:, 3:]
# axis=1,横向(列向)堆叠,axis=0,纵向(行向)堆叠
# 内连接(去除悬浮元组)与外连接(保留悬浮元组)
innerjoin = pd.concat([rs1, rs2], axis=1, join='inner')
outerjoin = pd.concat([rs1, rs2], axis=1, join='outer')
# 当两张表完全一致时,直接完全按轴拼接
join = pd.concat([rs1, rs1], axis=1, join='outer')

# (2)主键合并merge/也是连接,但不会出现堆叠(所有列重复出现),会按照主键合并(主键不会重复)
xx1 = pd.read_csv(r'.\tmp\xsxx.csv', encoding='gbk')  # 读取信息表
xx2 = pd.read_csv(r'.\tmp\xscj.csv', encoding='gbk')
# “学号”转换为字符串格式,保证左右连接表格的数据格式一致,为合并做准备(也可以不转换)
# xx1['学号'] = xx1['学号'].astype('str')
# xx2['学号'] = xx2['学号'].astype('str')
# 分别写出左右表的主键(连接的必要)
xx_detail = pd.merge(xx1.iloc[:, :2], xx2.iloc[:, :2], left_on='学号', right_on='学号')
# xx_detail = pd.merge(xx1.iloc[:, :2], xx1.iloc[:, :2], left_on='学号', right_on='学号')
# print("学生信息表与成绩表连接:\n", xx_detail)

# (3)合并重复数据combine_first(两相同表对比可以互相解决缺失值)
combine = rs.combine_first(rs)

'''4.数据清洗'''
# (1)重复值处理
# ①记录重复duplicated
# 只有指定数据中行/列全部一致才会认为重复,缺失值不一样都不行
# 指定列中是否有重复值,subset关键字可以不写出
dup1 = xx_detail.duplicated(subset=['姓名'])  # 查找重复值位置
dup2 = xx_detail['姓名'].drop_duplicates()  # 去除重复值

# ②特征重复(相关性过高/异名同义)
# import scipy
#
# corr1 = rs[['工作时间', '薪水']].corr(method='kendall')
# corr2 = rs.corr(method='kendall')
# print(corr1)

# 特征重复例子(不用corr,手动查重)
detail = pd.read_csv(r'.\tmp\meal_order_detail.csv', index_col=0, encoding='utf-8')
def FeatureEquals(df):
    # 建立以传入DataFrame的列标签为行、列标签的框架(特征矩阵)
    dfEquals = pd.DataFrame([], columns=df.columns, index=df.columns)
    for i in df.columns:
        for j in df.columns:
            # 以原数据集列之间的关系判断是否为重复特征
            dfEquals.loc[i, j] = df.loc[:, i].equals(df.loc[:, j])
    return dfEquals
detEquals = FeatureEquals(detail)
# print('detail的特征相等矩阵的前5行5列为:\n', detEquals.iloc[:5, :5])
lenDet = detEquals.shape[0]  # 特征列表长度
dupCol = []  # 去重列表
for k in range(lenDet):
    for l in range(k+1, lenDet):  # 对角矩阵,看右上角是不是True就行了
        if detEquals.iloc[k, l] & (detEquals.columns[l] not in dupCol):
            dupCol.append(detEquals.columns[l])
# 进行去重操作
# print('需要删除的列为:', dupCol)
# 沿列方向删除
detail.drop(dupCol, axis=1, inplace=True)
# shape = (a,b) shape[1]列数=b(第二维度),[0]行数=a(第一维度)
# print('删除多余列后detail的特征数目为:', detail.shape[1])

# (2)缺失值处理
# 查缺失值
null1 = rs.isnull()
null2 = rs.notnull()
# ①删除缺失值dropna删记录或特征
# 沿行方向(纵轴)删除,默认值1列向(横轴)删除
# any有缺失值就删(默认),all全为缺失值才删,subset指定行列
null3 = rs.dropna(axis=0, how='all')
# ②替换缺失值
# 可指定替换方式,如指定值/ffill用上个非缺失值补,bfill用下个非缺失值补
null4 = rs['小时报酬'].fillna(rs['小时报酬'].mean())
# ③插值法
# 利用函数确定值,使用scipy库
# 线性插值例子
# from scipy.interpolate import interp1d
# x=np.array([1,2,3,4,5,8,9,10]) ##创建自变量x
# y1=np.array([2,8,18,32,50,128,162,200]) ##创建因变量y1
# y2=np.array([3,5,7,9,11,17,19,21]) ##创建因变量y2
# LinearInsValue1 = interp1d(x,y1,kind='linear') ##线性插值拟合x,y1,生成函数
# LinearInsValue2 = interp1d(x,y2,kind='linear') ##线性插值拟合x,y2
# print('当x为6、7时,使用线性插值y1为:',LinearInsValue1([6,7])) # 给x找对应y
# print('当x为6、7时,使用线性插值y2为:',LinearInsValue2([6,7]))
# 拉格朗日插值例子
# from scipy.interpolate import lagrange
# LargeInsValue1 = lagrange(x,y1) ##拉格朗日插值拟合x,y1
# LargeInsValue2 = lagrange(x,y2) ##拉格朗日插值拟合x,y2
# print('当x为6,7时,使用拉格朗日插值y1为:',LargeInsValue1([6,7]))
# print('当x为6,7时,使用拉格朗日插值y2为:',LargeInsValue2([6,7]))
# 样条插值例子
# from scipy.interpolate import make_interp_spline
# SplineInsValue1 = make_interp_spline(x,y1)##样条插值拟合x,y
# SplineInsValue2 = make_interp_spline(x,y2)
# print('当x为6,7时,使用样条插值y1为:',SplineInsValue1([6,7]))
# print('当x为6,7时,使用样条插值y2为:',SplineInsValue2([6,7]))

# (3)异常值处理
# ①3theta(标准差)/拉依达法则
# 定义拉依达准则识别异常值函数
def outRange(Ser1):
    # 如果在3*std区域之外的就是误差的,得到一系列True值的列表
    boolInd = (Ser1 < Ser1.mean() - 3*Ser1.std()) | (Ser1 > Ser1.mean() + 3*Ser1.std())
    index = np.arange(Ser1.shape[0])[boolInd]  # 按照行长度建立数组,但是只保留下为True的值,即异常值的index
    outrange = Ser1.iloc[index]  # 生成异常值dataframe
    return outrange
outlier = outRange(detail['counts'])
print('使用拉依达准则判定异常值个数为:', outlier.shape[0])
print('异常值的最大值为:', outlier.max())
print('异常值的最小值为:', outlier.min())

# ②箱线图
p = plt.boxplot(detail['counts'], notch=True)  # 箱线图
outlier1 = p['fliers'][0].get_ydata()  # fliers为异常值的标签
# plt.savefig('./tmp/菜品异常数据识别.png')
print('销售量数据异常值个数为:', len(outlier1))
print('销售量数据异常值的最大值为:', max(outlier1))
print('销售量数据异常值的最小值为:', min(outlier1))


'''5.数据标准化(归约)'''
# (1)离差标准化
# 自定义离差标准化函数
def MinMaxScale(data):
    data = (data - data.min()) / (data.max() - data.min())
    return data
# data1 = MinMaxScale(detail['counts'])
# data2 = MinMaxScale(detail['amounts'])
# data3 = pd.concat([data1, data2], axis=1)
# print('离差标准化之前销量和售价数据为:\n',
#     detail[['counts', 'amounts']].head(5))
# print('离差标准化之后销量和售价数据为:\n', data3.head(5))

# (2)z分数标准化
# 自定义标准差标准化函数
def StandardScaler(data):
    data = (data - data.mean()) / data.std()
    return data
# 对菜品订单表售价和销量做标准化
# data4 = StandardScaler(detail['counts'])
# data5 = StandardScaler(detail['amounts'])
# data6 = pd.concat([data4, data5], axis=1)
# print('z分数标准化之前销量和售价数据为:\n',
#     detail[['counts', 'amounts']].head(5))
# print('z分数标准化之后销量和售价数据为:\n', data6.head(5))

# (3)小数定标标准化


'''6.数据转换'''
# (1)哑变量(非数值型变量,无法直接用于数据分析)
# pd.get_dummies,输入的数据可以是array,series,dataframe(一维或多维)
data2 = rs.loc[:, '部门']
print('哑变量处理前的数据为:\n', data2)
print('哑变量处理后的数据为:\n', pd.get_dummies(data2))

# (2)离散化(有的算法输入参数不希望是连续值)
# pd.cut,输入的数据只能是array或series(一维)
# bin设置离散化后的分类数
print(pd.cut(rs['小时报酬'], bins=4))
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值