利用python进行数据分析之数据规整化
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用python进行数据分析之数据规整化相关的知识,希望对你有一定的参考价值。
数据分析和建模大部分时间都用在数据准备上,数据的准备过程包括:加载,清理,转换与重塑。
合并数据集
pandas对象中的数据可以通过一些内置方法来进行合并:
pandas.merge可根据一个或多个键将不同DataFrame中的行连接起来,实现类似于数据库中的连接操作。
pandas.cancat表示沿着一条轴将多个对象堆叠到一起。
实例方法combine_first可以将重复数据编接在一起,用一个对象中的值填充另一个对象的缺失值。
下面将进行分别讲解:
1、数据库风格的DateFrame合并
数据集的合并运算是通过一个或者多个键将行连接起来,主要使用的merge或者join方法。
>>> import pandas as pd >>> from pandas import DataFrame >>> import numpy as np >>> df1=DataFrame({‘key‘:[‘b‘,‘b‘,‘a‘,‘c‘,‘a‘,‘a‘,‘b‘],‘data1‘:range(7)}) >>> df2=DataFrame({‘key‘:[‘a‘,‘b‘,‘d‘],‘data2‘:range(3)}) >>> pd.merge(df1,df2) data1 key data2 0 0 b 1 1 1 b 1 2 6 b 1 3 2 a 0 4 4 a 0 5 5 a 0 #未显示指定用何列拼接,默认用重叠列的作为键,最好显示指定 >>> pd.merge(df1,df2,on=‘key‘) data1 key data2 0 0 b 1 1 1 b 1 2 6 b 1 3 2 a 0 4 4 a 0 5 5 a 0
#当两个对象列明不同可以进行分别指定 >>> df3=DataFrame({‘lkey‘:[‘b‘,‘b‘,‘a‘,‘c‘,‘a‘,‘a‘,‘b‘],‘data1‘:range(7)}) >>> df4=DataFrame({‘rkey‘:[‘a‘,‘b‘,‘d‘],‘data2‘:range(3)}) >>> pd.merge(df3,df4,left_on=‘lkey‘,right_on=‘rkey‘) data1 lkey data2 rkey 0 0 b 1 b 1 1 b 1 b 2 6 b 1 b 3 2 a 0 a 4 4 a 0 a 5 5 a 0 a #默认情况下merge函数进行的是交集操作,可以指定how参数来实现左右连接与并集(outer)
#根据多个键进行合并,传入一个由列名组成的列表即可 >>> left=DataFrame({‘key1‘:[‘foo‘,‘foo‘,‘bar‘],‘key2‘:[‘one‘,‘two‘,‘three‘],‘lval‘:[1,2,3]}) >>> right=DataFrame({‘key1‘:[‘foo‘,‘foo‘,‘bar‘,‘bar‘],‘key2‘:[‘one‘,‘two‘,‘one‘,‘two‘],‘rval‘:[4,5,6,7]}) >>> pd.merge(left,right,on=[‘key1‘,‘key2‘],how=‘outer‘) key1 key2 lval rval 0 foo one 1 4 1 foo two 2 5 2 bar three 3 NaN 3 bar one NaN 6 4 bar two NaN 7
对于合并运算需要考虑的最后一个问题是对重复列名的处理,merge有一个suffixes选项,用于指定附加到左右两个DataFrame对象的重叠列名上的字符串:
>>> pd.merge(left,right,on=‘key1‘) key1 key2_x lval key2_y rval 0 foo one 1 one 4 1 foo one 1 two 5 2 foo two 2 one 4 3 foo two 2 two 5 4 bar three 3 one 6 5 bar three 3 two 7 >>> pd.merge(left,right,on=‘key1‘,suffixes=(‘_left‘,‘_right‘)) key1 key2_left lval key2_right rval 0 foo one 1 one 4 1 foo one 1 two 5 2 foo two 2 one 4 3 foo two 2 two 5 4 bar three 3 one 6 5 bar three 3 two 7
merge函数的参数表 | |
left | 参与合并的左侧DataFrame |
right | 参与合并的右侧DataFrame |
how | 选定参与合并的方式(inner,outer,left等) |
on | 用于连接的列名 |
left_on | 左侧DataFrame中用于连接的键 |
right_on | 右侧DataFrame中用于连接的键 |
sort | 根据连接键对合并后的数据进行排序,默认为True |
suffixes |
字符串元组,用于追加到重叠列名的末尾 |
2、索引上的合并
有时,DataFrame中的连接位于其索引中,在此种情况下可以传入left_index=True或者right_index=True以说明索引应该被用作连接键:
>>> left1=DataFrame({‘key‘:[‘a‘,‘b‘,‘a‘,‘a‘,‘b‘,‘c‘],‘value‘:range(6)}) >>> right1=DataFrame({‘group‘:[3.5,7]},index=[‘a‘,‘b‘]) >>> left1 key value 0 a 0 1 b 1 2 a 2 3 a 3 4 b 4 5 c 5 >>> right1 group a 3.5 b 7.0
对于层次化索引数据,相对更为复杂些,在这种情况下,必须以列表的形式指明用作合并键的多个列
>>> lenth=DataFrame({‘key1‘:[‘ohio‘,‘ohio‘,‘ohio‘,‘nevada‘,‘nevada‘],‘key2‘:[2000,2001,2002,2001,2002],‘data‘:np.arange(5)}) >>> righth=DataFrame(np.arange(12).reshape((6,2)),index=[[‘neveda‘,‘neveda‘,‘ohio‘,‘ohio‘,‘ohio‘,‘ohio‘],[2001,2000,2000,2000,2001,2002]],columns=[‘event1‘,‘event2‘]) >>> lenth data key1 key2 0 0 ohio 2000 1 1 ohio 2001 2 2 ohio 2002 3 3 nevada 2001 4 4 nevada 2002 >>> righth event1 event2 neveda 2001 0 1 2000 2 3 ohio 2000 4 5 2000 6 7 2001 8 9 2002 10 11 >>> pd.merge(lenth,righth,left_on=[‘key1‘,‘key2‘],right_index=True) data key1 key2 event1 event2 0 0 ohio 2000 4 5 0 0 ohio 2000 6 7 1 1 ohio 2001 8 9 2 2 ohio 2002 10 11
DataFrame还有一个join实例方法,它可以更为方便的实现按索引合并,还可以合并多个带有相同或者相似索引的DataFrame对象,而不管其是否有重叠的列:
>>> left2=DataFrame([[1,2],[3,4],[5,6]],index=[‘a‘,‘c‘,‘e‘],columns=[‘ohio‘,‘nevada‘]) >>> left2 ohio nevada a 1 2 c 3 4 e 5 6 >>> right2=DataFrame([[7,8],[9,10],[11,12],[13,14]],index=[‘b‘,‘c‘,‘d‘,‘e‘],columns=[‘missouri‘,‘alambda‘]) >>> right2 missouri alambda b 7 8 c 9 10 d 11 12 e 13 14 >>> left2.join(right2,how=‘outer‘) ohio nevada missouri alambda a 1 2 NaN NaN b NaN NaN 7 8 c 3 4 9 10 d NaN NaN 11 12 e 5 6 13 14
3、轴向连接
纵向上,numpy有一个用于合并原始numpy数组的concatenation函数:
>>> arr=np.arange(12).reshape((3,4)) >>> arr array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> np.concatenate([arr,arr],axis=1) array([[ 0, 1, 2, 3, 0, 1, 2, 3], [ 4, 5, 6, 7, 4, 5, 6, 7], [ 8, 9, 10, 11, 8, 9, 10, 11]]) >>> np.concatenate([arr,arr],axis=0) array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11], [ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
#pandas的concat函数提供了一种能够解决这些问题的可靠方式,默认情况下,concat在0轴上工作, >>> s1=pd.Series([0,1],index=[‘a‘,‘b‘]) >>> s2=pd.Series([2,3,4],index=[‘c‘,‘d‘,‘e‘]) >>> s3=pd.Series([5,6],index=[‘f‘,‘g‘]) >>> pd.concat([s1,s2,s3]) a 0 b 1 c 2 d 3 e 4 f 5 g 6 dtype: int64
#axis=1时,得到一个DataFrame对象 >>> pd.concat([s1,s2,s3],axis=1) 0 1 2 a 0 NaN NaN b 1 NaN NaN c NaN 2 NaN d NaN 3 NaN e NaN 4 NaN f NaN NaN 5 g NaN NaN 6
可以通过join_axes指定要在其他轴上使用的索引:
>>> s4=pd.concat([s1*5,s3]) >>> s4 a 0 b 5 f 5 g 6 dtype: int64 >>> pd.concat([s1,s4],axis=1,join_axes=[[‘a‘,‘c‘,‘b‘,‘e‘]]) 0 1 a 0 0 c NaN NaN b 1 5 e NaN NaN
当你需要区分参与连接的片段时,可以在连接轴上创建一个层次化索引,使用key参数可以达到这个目的
>>> result=pd.concat([s1,s2,s3],keys=[‘one‘,‘two‘,‘three‘]) >>> result one a 0 b 1 two c 2 d 3 e 4 three f 5 g 6 dtype: int64
#如果沿着axis=1对Series进行合并,则keys会变成合并后DataFrame的列头 >>> pd.concat([s1,s2,s3],keys=[‘one‘,‘two‘,‘three‘],axis=1) one two three a 0 NaN NaN b 1 NaN NaN c NaN 2 NaN d NaN 3 NaN e NaN 4 NaN f NaN NaN 5 g NaN NaN 6
最后一个需要考虑的问题是,跟当前分析无关的DataFrame索引,直接传入ignore_index=True即可:
>>> df1=DataFrame(np.random.randn(3,4),columns=[‘a‘,‘b‘,‘c‘,‘d‘]) >>> df2=DataFrame(np.random.randn(2,3),columns=[‘b‘,‘d‘,‘a‘]) >>> df1 a b c d 0 -1.928978 -1.202455 -0.180614 0.693538 1 -1.234482 0.664544 0.259534 0.429279 2 0.305255 0.133844 0.934637 0.243345 >>> df2 b d a 0 -1.582425 0.055378 0.288906 1 -0.381170 0.731310 -0.661805 >>> pd.concat([df1,df2],ignore_index=True) a b c d 0 -1.928978 -1.202455 -0.180614 0.693538 1 -1.234482 0.664544 0.259534 0.429279 2 0.305255 0.133844 0.934637 0.243345 3 0.288906 -1.582425 NaN 0.055378 4 -0.661805 -0.381170 NaN 0.731310 #注意区分与下面区别 >>> pd.concat([df1,df2]) a b c d 0 -1.928978 -1.202455 -0.180614 0.693538 1 -1.234482 0.664544 0.259534 0.429279 2 0.305255 0.133844 0.934637 0.243345 0 0.288906 -1.582425 NaN 0.055378 1 -0.661805 -0.381170 NaN 0.731310
4、合并重叠数据
还有一种数据不能用简单的合并或者连接运算来处理比如你有可能索引全部或部分重叠的两个数据集:
>>> a=Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],index=[‘f‘,‘e‘,‘d‘,‘c‘,‘b‘,‘a‘]) >>> b=Series(np.arange(len(a),dtype=np.float64),index=[‘f‘,‘e‘,‘d‘,‘c‘,‘b‘,‘a‘]) >>> a f NaN e 2.5 d NaN c 3.5 b 4.5 a NaN dtype: float64 >>> b f 0 e 1 d 2 c 3 b 4 a 5 dtype: float64 >>> np.where(pd.isnull(a),b,a) array([ 0. , 2.5, 2. , 3.5, 4.5, 5. ]) #可以看作用参数对象中的数据为调用者对象的缺失数据打补丁
也可用combine_first方法
>>> df1=DataFrame({‘a‘:[1,np.nan,5,np.nan],‘b‘:[np.nan,2,np.nan,6],‘c‘:range(2,18,4)}) >>> df1 a b c 0 1 NaN 2 1 NaN 2 6 2 5 NaN 10 3 NaN 6 14 >>> df2=DataFrame({‘a‘:[5,4,np.nan,3,7],‘b‘:[np.nan,3,4,6,8]}) >>> df2 a b 0 5 NaN 1 4 3 2 NaN 4 3 3 6 4 7 8 >>> df1.combine_first(df2) a b c 0 1 NaN 2 1 4 2 6 2 5 4 10 3 3 6 14 4 7 8 NaN
重塑和轴向旋转
1、重塑层次化索引
层次化索引技术为DataFrame数据重拍运算提供了一种具有良好一致性的方式,主要功能有二:
stack,将数据的列旋转为行
unstack,将数据的行旋转为列
>>> data=DataFrame(np.arange(6).reshape((2,3)),index=[‘ohio‘,‘colorado‘],columns=[‘one‘,‘two‘,‘three‘]) >>> data one two three ohio 0 1 2 colorado 3 4 5 >>> data.index Index([u‘ohio‘, u‘colorado‘], dtype=‘object‘) >>> data.index.name=‘state‘ >>> data.columns.name=‘number‘ >>> data number one two three state ohio 0 1 2 colorado 3 4 5 >>> data.stack() state number ohio one 0 two 1 three 2 colorado one 3 two 4 three 5 dtype: int32
#将列转化为行,得到一个Series
#对于一个层次化索引的Series,可以用unstack将其重排为一个DataFrame
默认情况下unstack操作的是最内层的,可传入分层级别的编号和名称参数,即可对其他级别进行untack操作:
>>> result=data.stack() >>> result state number ohio one 0 two 1 three 2 colorado one 3 two 4 three 5 dtype: int32 >>> result.unstack(0) state ohio colorado number one 0 3 two 1 4 three 2 5 >>> result.unstack(‘state‘) state ohio colorado number one 0 3 two 1 4 three 2 5
在对DataFrame,进行unset操作时,作为旋转轴的级别将会成为结果中的最低级别(即旋转轴索引将成为最内层索引):
>>> df=DataFrame({‘left‘:result,‘right‘:result+5},columns=[‘left‘,‘right‘]) >>> df.columns.name=‘side‘ >>> df side left right state number ohio one 0 5 two 1 6 three 2 7 colorado one 3 8 two 4 9 three 5 10 >>> df.unstack(‘state‘) side left right state ohio colorado ohio colorado number one 0 3 5 8 two 1 4 6 9 three 2 5 7 10 >>> df.unstack(‘state‘).stack(‘side‘) state ohio colorado number side one left 0 3 right 5 8 two left 1 4 right 6 9 three left 2 5 right 7 10
数据转换
除了数据合并与重排之外,另一类重要的操作是过滤,清理。
1、移除重复数据
DataFrame的duplicated方法返回一个布尔型Series,表示各行是否为重复行
>>> data=DataFrame({‘k1‘:[‘one‘]*3+[‘two‘]*4,‘k2‘:[1,1,2,3,3,4,4]}) >>> data k1 k2 0 one 1 1 one 1 2 one 2 3 two 3 4 two 3 5 two 4 6 two 4 >>> data.duplicated() 0 False 1 True 2 False 3 False 4 True 5 False 6 True dtype: bool #drop_duplicates方法用于返回一个移除了重复行的DataFrame,删除那些为True的行 >>> data.drop_duplicates() k1 k2 0 one 1 2 one 2 3 two 3 5 two 4 #可以指定过滤重复列的项 >>> data.drop_duplicates([‘k1‘]) k1 k2 0 one 1 3 two 3
#以上两个方法默认保留第一个出现的组合值,传入take_last=True则可以保留最后一个
以上是关于利用python进行数据分析之数据规整化的主要内容,如果未能解决你的问题,请参考以下文章