1.Pandas简介
2.两种数据结构
3.相关操作(索引,查询,统计分析,SQL操作,对缺失值处理,excel的数据透视表功能,多层索引)
1.Pandas简介
Pandas是基于Numpy的一个开源python库,它被广泛用于快速分析数据,以及数据清洗和准备等工作。
2.两种数据结构
pandas中有两类非常重要的数据结构,就是序列Series和数据框DataFrame.Series类似于NumPy中的一维数组,可以使用一维数组的可用函数和方法,而且还可以通过索引标签的方式获取数据,还具有索引的自动对齐功能;DataFrame类似于numpy中的二维数组,同样可以使用numpy数组的函数和方法,还具有一些其它灵活的使用。
pd.Series():
通过一维数组创建序列
通过字典方式创建序列
通过DataFrame中的某一行或者某一列创建序列
#第一种 通过一维数组创建序列import pandas as pdimport numpy as nparr1=np.arange(10)print("数组arr1:",arr1)print("arr1的数据类型:",type(arr1))s1=pd.Series(arr1)print("序列s1:\n",s1)print("s1的数据类型:",type(s1))
数组arr1: [0 1 2 3 4 5 6 7 8 9]arr1的数据类型: <class 'numpy.ndarray'>序列s1: 0 01 12 23 34 45 56 67 78 89 9dtype: int64s1的数据类型: <class 'pandas.core.series.Series'>
#第二种 通过字典的方式创建序列dict1={'a':1,'b':2,'c':3,'d':4,'e':5}print("字典dict1:",dict1)print("dict1的数据类型:",type(dict1))s2=pd.Series(dict1)print("序列s2:",s2)print("s2的数据类型:",type(s2))
字典dict1: {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}dict1的数据类型: <class 'dict'>序列s2: a 1b 2c 3d 4e 5dtype: int64s2的数据类型: <class 'pandas.core.series.Series'>
pd.DataFrame():
通过二维数组创建
通过字典方式创建
通过数据框创建
#第三种 通过DataFrame中的某一行或某一列创建序列#讲这种方法之前,我们需要先学习一下DataFrame的创建,DataFrame的创建依然有三种方法###第①种 通过二维数组创建数据框print("第一种方法创建DataFrame")arr2=np.array(np.arange(12)).reshape(4,3)print("数组2:",arr2)print("数组2的类型",type(arr2))df1=pd.DataFrame(arr2)print("数据框1:\n",df1)print("数据框1的类型:",type(df1))print("------------------------------------------------")print("\n")###第②种 通过字典的方式创建数据框print("第二种方法创建DataFrame")dict2={'a':[1,2,3,4],'b':[5,6,7,8],'c':[9,10,11,12],'d':[13,14,15,16]}print("字典2-字典列表:",dict2)print("字典2的类型",type(dict2))df2=pd.DataFrame(dict2)print("数据框2:\n",df2)print("数据框2的类型:",type(df2))print("------------------------------------------------")print("\n")dict3={'one':{'a':1,'b':2,'c':3,'d':4}, 'two':{'a':5,'b':6,'c':7,'d':8}, 'three':{'a':9,'b':10,'c':11,'d':12}}print("字典3-嵌套字典:",dict3)print("字典3的类型",type(dict3))df3=pd.DataFrame(dict3)print("数据框3:\n",df3)print("数据框3的类型:",type(df3))print("------------------------------------------------")print("\n")###第①种 通过数据框创建数据框print("第三种方法创建DataFrame")df4=df3[['one','three']]print("数据框4:\n",df4)print("数据框4的类型:",type(df4))print("------------------------------------------------")print("\n")print("------------------------------------------------")print("------------------------------------------------")print("\n")#接下来就是通过DataFrame中的某一行或某一列创建序列s3=df3['one'] #直接拿出数据框3中第一列print("序列3:\n",s3)print("序列3的类型:",type(s3))print("------------------------------------------------")s4=df3.iloc[0] #df3['a'] #直接拿出数据框3中第一行--ilocprint("序列4:\n",s4)print("序列4的类型:",type(s4))
第一种方法创建DataFrame数组2: [[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]]数组2的类型 <class 'numpy.ndarray'>数据框1: 0 1 20 0 1 21 3 4 52 6 7 83 9 10 11数据框1的类型: <class 'pandas.core.frame.DataFrame'>------------------------------------------------第二种方法创建DataFrame字典2-字典列表: {'a': [1, 2, 3, 4], 'b': [5, 6, 7, 8], 'c': [9, 10, 11, 12], 'd': [13, 14, 15, 16]}字典2的类型 <class 'dict'>数据框2: a b c d0 1 5 9 131 2 6 10 142 3 7 11 153 4 8 12 16数据框2的类型: <class 'pandas.core.frame.DataFrame'>------------------------------------------------字典3-嵌套字典: {'one': {'a': 1, 'b': 2, 'c': 3, 'd': 4}, 'two': {'a': 5, 'b': 6, 'c': 7, 'd': 8}, 'three': {'a': 9, 'b': 10, 'c': 11, 'd': 12}}字典3的类型 <class 'dict'>数据框3: one two threea 1 5 9b 2 6 10c 3 7 11d 4 8 12数据框3的类型: <class 'pandas.core.frame.DataFrame'>------------------------------------------------第三种方法创建DataFrame数据框4: one threea 1 9b 2 10c 3 11d 4 12数据框4的类型: <class 'pandas.core.frame.DataFrame'>------------------------------------------------------------------------------------------------------------------------------------------------序列3: a 1b 2c 3d 4Name: one, dtype: int64序列3的类型: <class 'pandas.core.series.Series'>------------------------------------------------序列4: one 1two 5three 9Name: a, dtype: int64序列4的类型: <class 'pandas.core.series.Series'>
3.相关操作
3.1 数据索引index
无论数据框还是序列,最左侧始终有一个非原始数据对象,这个就是接下来要介绍的数据索引。通过索引获取目标数据,对数据进行一系列的操作。
3.1.1 通过索引值或索引标签获取数据
#1.通过索引值或者索引标签获取数据s5=pd.Series(np.array([1,2,3,4,5,6]))print(s5) #如果不给序列一个指定索引值,序列会自动生成一个从0开始的自增索引
0 11 22 33 44 55 6dtype: int32
s5.index #通过index属性获取序列的索引值
RangeIndex(start=0, stop=6, step=1)
s5.index=['a','b','c','d','e','f'] #为index重新赋值s5
a 1b 2c 3d 4e 5f 6dtype: int32
#序列有了索引,就可以通过索引获取数据s5[3]
4
s5['e']
5
s5[[1,3,5]]
b 2d 4f 6dtype: int32
s5[:4]
a 1b 2c 3d 4dtype: int32
s5['c':]
c 3d 4e 5f 6dtype: int32
s5['b':'e'] #通过索引标签获取数据,末端标签的数据也是返回的,
b 2c 3d 4e 5dtype: int32
3.1.2 自动化对齐
#当对两个s6=pd.Series(np.array([10,15,20,30,55,80]),index=['a','b','c','d','e','f'])print("序列6:",s6)s7=pd.Series(np.array([12,11,13,15,14,16]),index=['a','c','g','b','d','f'])print("序列7:",s7)print(s6+s7) #s6中不存在g索引,s7中不存在e索引,所以数据运算会产生两个缺失值NaN。#可以注意到这里的算术运算自动实现了两个序列的自动对齐#对于数据框的对齐,不仅是行索引的自动对齐,同时也会对列索引进行自动对齐,数据框相当于二维数组的推广print(s6/s7)
序列6: a 10b 15c 20d 30e 55f 80dtype: int32序列7: a 12c 11g 13b 15d 14f 16dtype: int32a 22.0b 30.0c 31.0d 44.0e NaNf 96.0g NaNdtype: float64a 0.833333b 1.000000c 1.818182d 2.142857e NaNf 5.000000g NaNdtype: float64
3.3 pandas查询数据
通过布尔索引有针对的选取原数据的子集,指定行,指定列等。
test_data=pd.read_csv('test_set.csv')# test_data.drop(['ID'],inplace=True,axis=1)test_data.head()
将字符分解为数字
test_data['job'],jnum=pd.factorize(test_data['job'])test_data['job']=test_data['job']+1test_data['marital'],jnum=pd.factorize(test_data['marital'])test_data['marital']=test_data['marital']+1test_data['education'],jnum=pd.factorize(test_data['education'])test_data['education']=test_data['education']+1test_data['default'],jnum=pd.factorize(test_data['default'])test_data['default']=test_data['default']+1test_data['housing'],jnum=pd.factorize(test_data['housing'])test_data['housing']=test_data['housing']+1test_data['loan'],jnum=pd.factorize(test_data['loan'])test_data['loan']=test_data['loan']+1test_data['contact'],jnum=pd.factorize(test_data['contact'])test_data['contact']=test_data['contact']+1test_data['month'],jnum=pd.factorize(test_data['month'])test_data['month']=test_data['month']+1test_data['poutcome'],jnum=pd.factorize(test_data['poutcome'])test_data['poutcome']=test_data['poutcome']+1test_data.head()
#以上通过导入一个数据集进行操作#查询数据的前5行test_data.head()
#查询数据的末尾5行test_data.tail()
#查询指定的行test_data.iloc[[0,2,4,5,7]]
#查询指定的列test_data[['age','job','marital']].head()
#查询指定的行和列test_data.loc[[0,2,4,5,7],['age','job','marital']]
#一下通过布尔索引实现数据的自己查询#查询年龄为51的信息test_data[test_data['age']==51].head()
#查询工作为5以上的年龄在51的信息test_data[(test_data['age']==51) & (test_data['job']>=5)].head()
#查询工作为5以上,年龄在51的人员的housing,loan,contac和poutcometest_data[(test_data['age']==51) & (test_data['job']>=5)][['education','housing','loan','contact','poutcome']].head()
多个条件的查询,需要在&或者|的两端的条件括起来¶
3.4 对DateFrames进行统计分析
Pandas为我们提供了很多描述性统计分析的指标函数,包括,总和,均值,最小值,最大值等。
a=np.random.normal(size=10)d1=pd.Series(2*a+3)d2=np.random.f(2,4,size=10)d3=np.random.randint(1,100,size=10)print(d1)print(d2)print(d3)
0 5.8110771 2.9634182 2.2950783 0.2796474 6.5642935 1.1464556 1.9036237 1.1577108 2.9213049 2.397009dtype: float64[0.18147396 0.48218962 0.42565903 0.10258942 0.55299842 0.10859328 0.66923199 1.18542009 0.12053079 4.64172891][33 17 71 45 33 83 68 41 69 23]
d1.count() #非空元素的计算d1.min() #最小值d1.max() #最大值d1.idxmin() #最小值的位置d1.idxmax() #最大值的位置d1.quantile(0.1) #10%分位数d1.sum() #求和d1.mean() #平均数d1.median() #中位数d1.mode() #众数d1.var() #方差d1.std() #标准差d1.mad() #平均绝对偏差d1.skew() #偏度d1.kurt() #峰度
d1.describe() #一次性输出多个描述性统计指标
count 10.000000mean 2.743961std 2.006956min 0.27964725% 1.34418950% 2.34604475% 2.952890max 6.564293dtype: float64
#自定义一个函数,将这些统计描述指标全部汇总到一起def stats(x): return pd.Series([x.count(),x.min(),x.idxmin(),x.quantile(.25),x.median(), x.quantile(.75),x.mean(),x.max(),x.idxmax(),x.mad(),x.var(),x.std(),x.skew(),x.kurt()], index=['Count','Min','Which_Min','Q1','Median','Q3','Mean','Max','Which_Max','Mad','Var','Std','Skew', 'Kurt'])stats(d1)
Count 10.000000Min 0.279647Which_Min 3.000000Q1 1.344189Median 2.346044Q3 2.952890Mean 2.743961Max 6.564293Which_Max 4.000000Mad 1.456849Var 4.027872Std 2.006956Skew 1.045776Kurt 0.393228dtype: float64
#当实际工作中我们需要处理的是一系列的数值型数据框,可以使用apply函数将这个stats函数应用到数据框中的每一列df=pd.DataFrame(np.array([d1,d2,d3]).T,columns=['x1','x2','x3']) #将之前创建的d1,d2,d3数据构建数据框print(df.head())df.apply(stats)
x1 x2 x30 5.811077 0.181474 33.01 2.963418 0.482190 17.02 2.295078 0.425659 71.03 0.279647 0.102589 45.04 6.564293 0.552998 33.0
以上很简单的创建了数值型数据的统计性描述,但对于离散型数据就不能使用该方法了。我们在统计离散变量的观测数、唯一值个数、众数水平及个数,只需要使用describe方法就可以实现这样的统计了。
train_data=pd.read_csv('train_set.csv')# test_data.drop(['ID'],inplace=True,axis=1)train_data.head()
train_data['job'].describe() #离散型数据的描述
count 25317unique 12top blue-collarfreq 5456Name: job, dtype: object
test_data['job'].describe() #数值型数据的描述
count 10852.000000mean 5.593255std 2.727318min 1.00000025% 3.00000050% 6.00000075% 8.000000max 12.000000Name: job, dtype: float64
除了以上简单的描述性统计之外,还提供了连续变量的相关系数(corr)和协方差(cov)的求解
df
df.corr() #相关系数的计算方法可以调用pearson方法、kendall方法、或者spearman方法,默认使用的是pearson方法
df.corr('spearman')
df.corr('pearson')
df.corr('kendall')
#如果只关注某一个变量与其余变量的相关系数的话,可以使用corrwith,如下方只关注x1与其余变量的相关系数df.corrwith(df['x1'])
x1 1.000000x2 -0.075466x3 -0.393609dtype: float64
#数值型变量间的协方差矩阵df.cov()
3.5 panda实现SQL操作
# 增:添加新行或增加新列dict={'Name':['LiuShunxiang','Zhangshan'], 'Sex':['M','F'], 'Age':[27,23], 'Height':[165.7,167.2], 'weight':[61,63]}print(dict)student1=pd.DataFrame(dict)print(student1)dict={'Name':['Liu','Zhang'], 'Sex':['M','F'], 'Age':[27,23], 'Height':[165.7,167.2], 'weight':[61,63]}student2=pd.DataFrame(dict)
{'Name': ['LiuShunxiang', 'Zhangshan'], 'Sex': ['M', 'F'], 'Age': [27, 23], 'Height': [165.7, 167.2], 'weight': [61, 63]} Name Sex Age Height weight0 LiuShunxiang M 27 165.7 611 Zhangshan F 23 167.2 63
#将student2中的数据新增到student1中,可以通过concat函数实现student3=pd.concat([student1,student2],ignore_index='Ture') #concat函数对index无视student3
#添加新列---增加的新列没有赋值,就会出现NAN的形式pd.DataFrame(student2,columns=['Age','Heught','Name','Sex','weight','Score'])
# 删:删除表、观测行或变量列#删除整个数据框del student2student2
---------------------------------------------------------------------------NameError Traceback (most recent call last)<ipython-input-32-dbecb61e032f> in <module>()----> 1 student2NameError: name 'student2' is not defined
#删除指定行student3.drop([0])
#删除25岁以下的学生student3[student3['Age']<25]
#删除指定的列student3.drop(['Height','weight'],axis=1)
不论删除行还是列,都可以通过drop方法实现,只需要设定好删除的轴即可,即调整drop方法中的axis参数。默认参数为0,即删除行观测数据,如果需要删除列变量,则需要设置为1.
# 改:修改原始记录的值#如果发现表中的数据错了,如何更改原来得值呢?尝试结合布尔索引和赋值的方法student3
#假设需要修改liu学生的身高为173student3.loc[student3['Name']=='Liu','Height']=173student3
# 查:类似上边的数据查询部分# 聚合:groupby()student3.groupby('Sex').mean()
#多个分组变量,例如根据年龄和性别分组,计算身高和体重的平均值student3.groupby(['Sex','Age']).mean()
#对每个分组计算多个统计量student3.drop('Age',axis=1).groupby('Sex').agg([np.mean,np.median])
#排序:sort_valuesseries=pd.Series(np.array(np.random.randint(1,20,10)))series
0 71 192 73 194 195 146 77 188 39 5dtype: int32
series.sort_values() #默认按值升序排列
8 39 50 72 76 75 147 181 193 194 19dtype: int32
series.sort_values(ascending=False) #按降序排列
4 193 191 197 185 146 72 70 79 58 3dtype: int32
#数据框中按值排列student3.sort_values(by=['Sex','Age'])
#多表链接-mergedict2={'Name':['Alfred','Alice','Barbara','Carol','Henry','Jeffrey','Judy','Philip','Robert','william'], 'Score':[88,76,89,67,79,90,92,86,73,77]}score=pd.DataFrame(dict2)score
student3['Name']=['Alfred','Alice','Barbara','Carol']student3
#把学生表和成绩表做一个关联stu_score1=pd.merge(student3,score,on='Name') #默认情况下实现的是两个表之间的内连接,即返回两张表中共同部分的数据stu_score1
stu_score1=pd.merge(student3,score,on='Name',how='inner') stu_score1
使用how参数设置连接的方式,left为左连接,right为右连接,outer为外连接
stu_score2=pd.merge(student3,score,on='Name',how='left') #保留student3表中的所有信息,同时将score表的信息与之配对,能配多少配多少,对于没有配上的Name,将会显示成绩为Nanstu_score2
stu_score3=pd.merge(student3,score,on='Name',how='right') #保留score表中的所有信息,同时将student3表的信息与之配对,能配多少配多少,对于没有配上的score,将会显示Nanstu_score3
stu_score4=pd.merge(student3,score,on='Name',how='outer') stu_score4
3.6 对缺失值的处理
现实中的数据存在很多噪音的同时,缺失值也非常的常见。缺失值的存在会影响后期的数据分析或挖掘工作,那么缺失值的处理有哪些方法呢?
3.6.1 删除法
当数据中某个变量大部分值都会缺失值时,可以考虑删除该变量;
当缺失值时随机分布的,且缺失的数量并不是很多时,可以删除这些缺失的观测;
train_data.head()
offline_data=pd.read_csv('ccf_offline_stage1_train.csv')offline_data.head()
s=offline_data['Coupon_id']s.size
1754884
sum(pd.isnull(s)) #查看包含多少个缺失值
701602
#直接删除缺失值s.dropna()
1 11002.02 8591.03 1078.04 8591.06 8591.07 7610.08 11951.09 1532.010 12737.013 1097.015 10698.016 9776.017 12034.018 5054.019 7802.020 7610.022 2366.023 7531.024 11002.025 13490.027 6704.031 2705.032 1495.033 11166.035 11166.036 11197.037 111.038 7531.039 111.041 2840.0 ... 1754833 416.01754834 12097.01754835 11951.01754839 14031.01754843 10027.01754844 13118.01754845 2107.01754848 3469.01754849 10883.01754850 1807.01754851 7166.01754853 10050.01754854 4567.01754855 7379.01754856 13056.01754857 12034.01754858 1480.01754859 7751.01754860 17.01754861 3237.01754862 12034.01754866 111.01754869 4723.01754873 5686.01754876 5267.01754877 3739.01754878 5686.01754880 3739.01754882 1633.01754883 2705.0Name: Coupon_id, Length: 1053282, dtype: float64
默认情况下,dropna会删除任何含有缺失值的行
#构造数据框试试df=pd.DataFrame([[1,1,2],[3,5,np.nan],[13,21,34],[55,np.nan,10], [np.nan,np.nan,np.nan],[np.nan,1,2]],columns=['x1','x2','x3'])df
df.dropna()
df=pd.DataFrame([[1,1,2],[3,5,np.nan],[13,21,34],[55,np.nan,10], [np.nan,np.nan,np.nan],[np.nan,1,2]],columns=['x1','x2','x3'])df.dropna(how='all') #只删除所有行为缺失值的观测
df=pd.DataFrame([[1,1,2],[3,5,np.nan],[13,21,34],[55,np.nan,10], [np.nan,np.nan,np.nan],[np.nan,1,2]],columns=['x1','x2','x3'])df.dropna(how='any') #删除有行为缺失值的观测,
df=pd.DataFrame([[1,1,2,np.nan],[3,5,np.nan,np.nan],[13,21,34,np.nan],[55,np.nan,10,np.nan], [np.nan,np.nan,np.nan,np.nan],[np.nan,1,2,np.nan]],columns=['x1','x2','x3','x4'])print(df)df.dropna(how='all',axis=1) #删除全为nan的那些列
x1 x2 x3 x40 1.0 1.0 2.0 NaN1 3.0 5.0 NaN NaN2 13.0 21.0 34.0 NaN3 55.0 NaN 10.0 NaN4 NaN NaN NaN NaN5 NaN 1.0 2.0 NaN
#利用thresh,保留一些为nan的值df=pd.DataFrame([[1,1,2,np.nan],[3,5,np.nan,np.nan],[13,21,34,np.nan],[55,np.nan,10,np.nan], [np.nan,np.nan,np.nan,np.nan],[np.nan,1,2,np.nan]],columns=['x1','x2','x3','x4'])df.dropna(thresh=3) #在行方向上至少有3个非NAN的项保留
df=pd.DataFrame([[1,1,2,np.nan],[3,5,np.nan,np.nan],[13,21,34,np.nan],[55,np.nan,10,np.nan], [np.nan,np.nan,np.nan,np.nan],[np.nan,1,2,np.nan]],columns=['x1','x2','x3','x4'])df.dropna(thresh=1)
df=pd.DataFrame([[1,1,2,np.nan],[3,5,np.nan,np.nan],[13,21,34,np.nan],[55,np.nan,10,np.nan], [np.nan,np.nan,np.nan,np.nan],[np.nan,1,2,np.nan]],columns=['x1','x2','x3','x4'])df.dropna(thresh=3,axis=1) #在列方向上至少保留有3个非NAN的项保留
3.6.2 替补法
对于连续变量,如果变量的分布近似或就是正态分布的话,可以用均值替代那些缺失值;
如果变量是有偏的,可以使用中位数来代替那些缺失值;
对于离散型变量,一般使用众数去替换那些存在缺失的预测;
fillna函数的参数:
value:用于填充缺失值的标量值或者字典对象
method:插值方式,如果函数调用时,未指定其他参数的话默认值fill
axis:待填充的轴默认值axis=0
inplace:修改调用这对象而不产生副本
limit:(对于前向和后项填充)可以连续填充的最大数量
#使用一个常量来填补缺失值,可以使用fillna函数实现简单的填补工作#1用0填补所有缺失值df.fillna(0)
#2采用前项填充或后项填充df.fillna(method='ffill') #用一个观测值填充
df.fillna(method='bfill') #用后一个观测值填充--这样会导致最后边的无法填充Nan
#3使用常量填充不同的列df.fillna({'x1':1,'x2':2,'x3':3})
#4使用均值或中位数填充各自的列x1_median=df['x1'].median()x2_mean=df['x2'].mean()x3_mean=df['x3'].mean()print(x1_median,x2_mean,x3_mean)
8.0 7.0 12.0
df.fillna({'x1':x1_median,'x2':x2_mean,'x3':x3_mean})
使用填充法时,相对于常数填充或者前项、后项填充,使用各列众数,均值或中位数填充要更加合理些,这也是工作中常用的一个快捷手段。
3.7 实现excel的数据透视表功能
pivot_table(data,values=None,index=None,columns=None,aggfunc='mean', fill_value=None,margins=False,dropna=True,margins_name='All')
#data:需要进行数据透视表操作的数据框
#values:指定需要聚合的字段
#index:指定某些原始变量作为行索引
#columns:指定哪些离散的分组变量
#aggfunc:指定相应的聚合函数
#fill_values:使用一个常数替代缺失值,默认不替换
#margins:是否进行行或列的汇总,默认不汇总
#dropna:默认所有观测为缺失的列
#margins_name:默认行汇总或列汇总的名称为‘ALL’
test_data.head()
pd.pivot_table(test_data,values=['balance'],columns=['marital'])#marital作为分组变量,balance作为数值变量做统计汇总
#marital作为1个分组变量,balance,housing作为两个数值变量做统计汇总pd.pivot_table(test_data,values=['balance','housing'],columns=['marital'])
#marital,job作为2个分组变量,balance作为1个数值变量做统计汇总pd.pivot_table(test_data,values=['balance','housing'],columns=['marital','job'])
marital jobbalance 1 1 1228.493671 2 1785.391272 3 2353.951501 4 845.000000 5 1243.956701 6 977.805556 7 1364.432602 8 1243.585938 9 1579.081081 10 1952.578544 11 1270.040984 12 1749.975000 2 1 1355.333333 2 1501.268148 3 1890.900000 4 1205.809322 5 1438.189147 6 878.873606 7 1236.768448 8 1047.812500 9 1716.306931 10 1367.694737 11 2158.580000 12 814.833333 3 1 1166.673913 2 1801.176471 3 1454.990196 4 2946.000000 5 962.784141 6 940.809917 ... housing 1 7 1.601881 8 1.725361 9 1.459459 10 1.475096 11 1.573770 12 1.000000 2 1 1.393939 2 1.482963 3 1.300000 4 1.241525 5 1.533333 6 1.676580 7 1.587786 8 1.708333 9 1.257426 10 1.452632 11 1.540000 12 1.055556 3 1 1.239130 2 1.533088 3 1.235294 4 1.000000 5 1.550661 6 1.628099 7 1.657609 8 1.705521 9 1.513514 10 1.457143 11 1.571429 12 1.500000Length: 72, dtype: float64
#marital,job作为2个分组变量,balance,housing作为两个数值变量做统计汇总pd.pivot_table(test_data,values=['balance','housing'],columns=['marital','job'])
marital jobbalance 1 1 1228.493671 2 1785.391272 3 2353.951501 4 845.000000 5 1243.956701 6 977.805556 7 1364.432602 8 1243.585938 9 1579.081081 10 1952.578544 11 1270.040984 12 1749.975000 2 1 1355.333333 2 1501.268148 3 1890.900000 4 1205.809322 5 1438.189147 6 878.873606 7 1236.768448 8 1047.812500 9 1716.306931 10 1367.694737 11 2158.580000 12 814.833333 3 1 1166.673913 2 1801.176471 3 1454.990196 4 2946.000000 5 962.784141 6 940.809917 ... housing 1 7 1.601881 8 1.725361 9 1.459459 10 1.475096 11 1.573770 12 1.000000 2 1 1.393939 2 1.482963 3 1.300000 4 1.241525 5 1.533333 6 1.676580 7 1.587786 8 1.708333 9 1.257426 10 1.452632 11 1.540000 12 1.055556 3 1 1.239130 2 1.533088 3 1.235294 4 1.000000 5 1.550661 6 1.628099 7 1.657609 8 1.705521 9 1.513514 10 1.457143 11 1.571429 12 1.500000Length: 72, dtype: float64
很显然,这样的结果并不想Excel中预期的那样,该如何变成列联表的形式呢?很简单,只需将结果进行非堆叠操作即可。
pd.pivot_table(test_data,values=['balance','housing'],columns=['marital','job']).unstack()
这样的结果看起来更舒服一些
#使用多个聚合函数pd.pivot_table(test_data,values=['balance','housing'],columns=['marital'], aggfunc=[np.mean,np.median,np.std])
更多关于透视表的操作,大家可以参考《Pandas透视表(pivot_table)详解》
3.8 多层索引的使用
接下再讲一个Pandas中的重要功能,那就是多层索引。
序列的多层索引类似于Excel中如下形式。
#Series的多层索引s=pd.Series([1,2,3,4],index=[['小张','小张','老王','老王'], ['期中','期末','期中','期末']])s
小张 期中 1 期末 2老王 期中 3 期末 4dtype: int64
s[['小张']] #取回最外层索引为‘小张’的所有数据
小张 期中 1 期末 2dtype: int64
s[:,'期中'] #取回最内层所有为‘期中’的数据
小张 1老王 3dtype: int64
#将多层次索引的序列转换为数据框的形式s.unstack()
以上是对序列的多层次索引,接下来将对数据框的多层次索引,多层索引的形式类似excel中的如下形式。
#构造一个类似的高维数据框df=pd.DataFrame(np.random.randint(10,50,20).reshape(5,4), index=[['A','A','A','B','B'],[1,2,3,1,2]], columns=[['x','x','x','y'],['x1','x2','x3','y']])df
#通过外层索引取出大块数据df['x']
df.loc[['A'],:]
在数据框中使用多层索引,可以将整个数据集控制在二维表结构中,这对于数据重塑和基于分组的操作(如数据透视表的生成)比较有帮助。
#以test_data二维数据框为例,构造一个多层索引数据集pd.pivot_table(test_data,index=['marital','loan'])