python数据分析之:数据清理,转换,合并,重塑
Posted 一张红枫叶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python数据分析之:数据清理,转换,合并,重塑相关的知识,希望对你有一定的参考价值。
DataFrame合并:
merge运算是将一个或多个键将行链接起来。来看下面的这个例子:
In [5]: df1=DataFrame({\'key\':[\'b\',\'b\',\'a\',\'c\',\'a\',\'a\',\'b\'],\'data1\':range(7)})
In [6]: df2=DataFrame({\'key\':[\'a\',\'b\',\'d\'],\'data2\':range(3)})
In [7]: df1
Out[7]:
data1 key
0 0 b
1 1 b
2 2 a
3 3 c
4 4 a
5 5 a
6 6 b
In [8]: df2
Out[8]:
data2 key
0 0 a
1 1 b
2 2 d
df1和df2的key值中都含有a,b,d,不同的是在df1中有重复的key值,而在df2中key值都是唯一的。通过merge函数可以将df1和df2中key值相同的行都链接起来。这种操作就和数据库中的inner join操作是差不多的。因为可以看到在合并后的数据中,key=c和d的列不存在了,因为inner join是取的交集,其他方式还有left,right,outer的方式
In [9]: pd.merge(df1,df2)
Out[9]:
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
取并集的方式
In [15]: pd.merge(df1,df2,how=\'outer\')
Out[15]:
data1 key data2
0 0.0 b 1.0
1 1.0 b 1.0
2 6.0 b 1.0
3 2.0 a 0.0
4 4.0 a 0.0
5 5.0 a 0.0
6 3.0 c NaN
7 NaN d 2.0
但是上面这个merge函数并没有指定对哪个列进行连接,如果没有指定,merge将会将重叠列的列名当做键。df1和df2重叠的键就是key。但是这里最好指定下列的名称。pd.merge(df1,df2,on=\'key\')。注意这里指定列名称的时候,这个列名称必须是在合并数据中都存在的。比如如果指定on=’data1’就会报错,因为在df2中找不到data1的列
但是如果两个对象的列名不一样,也可以分别进行指定
df3=DataFrame({\'lkey\':[\'b\',\'b\',\'a\',\'c\',\'a\',\'a\',\'b\'],\'data1\':r
...: ange(7)})
df4=DataFrame({\'rkey\':[\'a\',\'b\',\'d\'],\'data2\':range(3)})
通过left_on和right_on来分别指定列
In [19]: pd.merge(df3,df4,left_on=\'lkey\',right_on=\'rkey\')
Out[19]:
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
前面讲到默认合并是inner,通过how来制定合并方式,how有outer,left,right三种方式
In [20]: pd.merge(df1,df2,on=\'key\',how=\'left\')
Out[20]:
data1 key data2
0 0 b 1.0
1 1 b 1.0
2 2 a 0.0
3 3 c NaN
4 4 a 0.0
5 5 a 0.0
6 6 b 1.0
right的方式
In [21]: pd.merge(df1,df2,on=\'key\',how=\'right\')
Out[21]:
data1 key data2
0 0.0 b 1
1 1.0 b 1
2 6.0 b 1
3 2.0 a 0
4 4.0 a 0
5 5.0 a 0
6 NaN d 2
merge参数
索引上的合并:
有时候,DataFrame中的连接键位于其索引中,在这种情况下,你可以传入left_index=True或right_index=True以说明索引应该被用作连接键
In [22]: left1=DataFrame({\'key\':[\'a\',\'b\',\'a\',\'a\',\'b\',\'c\'],\'value\':rang
...: e(6)})
In [24]: right1=DataFrame({\'group_val\':[3.5,7]},index=[\'a\',\'b\'])
In [29]: pd.merge(left1,right1,left_on=\'key\',right_index=True)
Out[29]:
key value group_val
0 a 0 3.5
2 a 2 3.5
3 a 3 3.5
1 b 1 7.0
4 b 4 7.0
通过这种方法,就把right1中group_val的值也一起合并起来了。当然同样的也可以采取并集的方式
In [30]: pd.merge(left1,right1,left_on=\'key\',right_index=True,how=\'out
...: er\')
Out[30]:
key value group_val
0 a 0 3.5
2 a 2 3.5
3 a 3 3.5
1 b 1 7.0
4 b 4 7.0
5 c 5 NaN
再来看下复杂的合并,关于层次化的索引。
In [32]: left1=DataFrame({\'key1\':[\'ohio\',\'ohio\',\'ohio\',\'nevada\',\'nevad
...: a\'],\'key2\':[2000,2001,2002,2001,2002],\'data\':np.arange(5.)})
In [34]: right1=DataFrame(np.arange(12).reshape((6,2)),index=[[\'nevada
...: \',\'nevada\',\'ohio\',\'ohio\',\'ohio\',\'ohio\'],[2001,2000,2000,2000,
...: 2001,2002]],columns=[\'event1\',\'event2\'])
In [35]: left1
Out[35]:
data key1 key2
0 0.0 ohio 2000
1 1.0 ohio 2001
2 2.0 ohio 2002
3 3.0 nevada 2001
4 4.0 nevada 2002
In [36]: right1
Out[36]:
event1 event2
nevada 2001 0 1
2000 2 3
ohio 2000 4 5
2000 6 7
2001 8 9
2002 10 11
对于多层次索引的数据,必须以列表的形式指明用过合作键的多个列,这里指定key1和key2
去并集的方式
In [40]: pd.merge(left1,right1,left_on=[\'key1\',\'key2\'],right_index=Tru
...: e)
Out[40]:
data key1 key2 event1 event2
0 0.0 ohio 2000 4 5
0 0.0 ohio 2000 6 7
1 1.0 ohio 2001 8 9
2 2.0 ohio 2002 10 11
3 3.0 nevada 2001 0 1
In [44]: pd.merge(left1,right1,left_on=[\'key1\',\'key2\'],right_index=Tru
...: e,how=\'outer\')
Out[44]:
data key1 key2 event1 event2
0 0.0 ohio 2000 4.0 5.0
0 0.0 ohio 2000 6.0 7.0
1 1.0 ohio 2001 8.0 9.0
2 2.0 ohio 2002 10.0 11.0
3 3.0 nevada 2001 0.0 1.0
4 4.0 nevada 2002 NaN NaN
4 NaN nevada 2000 2.0 3.0
也可以合并双方的索引。
In [45]: left2=DataFrame([[1,2],[3,4],[5,6]],index=[\'a\',\'c\',\'e\'],colum
...: ns=[\'ohio\',\'nevada\'])
In [47]: right2=DataFrame([[7,8],[9,10],[11,12],[13,14]],index=[\'b\',\'c
...: \',\'d\',\'e\'],columns=[\'missouri\',\'alabama\'])
In [46]: left2
Out[46]:
ohio nevada
a 1 2
c 3 4
e 5 6
In [48]: right2
Out[48]:
missouri alabama
b 7 8
c 9 10
d 11 12
e 13 1
将两个数据的所有列的数据全部集合起来。
In [49]: pd.merge(left2,right2,how=\'outer\',left_index=True,right_index
...: =True)
Out[49]:
ohio nevada missouri alabama
a 1.0 2.0 NaN NaN
b NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0
d NaN NaN 11.0 12.0
e 5.0 6.0 13.0 14.0
DataFrame还有一个join实例方法,它能更方便地实现按索引合并,它还可以用于合并多个带有相同或相似索引的DataFrame对象。而不管它们之间有没有重叠的列。对于上面的例子,我们可以join的方法来实现
In [50]: left2.join(right2,how=\'outer\')
Out[50]:
ohio nevada missouri alabama
a 1.0 2.0 NaN NaN
b NaN NaN 7.0 8.0
c 3.0 4.0 9.0 10.0
d NaN NaN 11.0 12.0
e 5.0 6.0 13.0 14.0
轴向连接
轴向连接也可以看做是连接concatenation的操作。
In [4]: arr=np.arange(12).reshape((3,4))
In [5]: arr
Out[5]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [6]: np.concatenate([arr,arr],axis=1)
Out[6]:
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]])
接下来看下pandas中的concat函数。对于pandas对象,由于具备索引,因此连接运算的时候需要考虑索引的连接。
In [9]: s1=Series([0,1],index=[\'a\',\'b\'])
In [10]: s1
Out[10]:
a 0
b 1
dtype: int64
In [11]: s2=Series([2,3,4],index=[\'c\',\'d\',\'e\'])
In [12]: s2
Out[12]:
c 2
d 3
e 4
dtype: int64
In [13]: s3=Series([5,6],index=[\'f\',\'g\'])
In [14]: s3
Out[14]:
f 5
g 6
dtype: int64
In [15]: pd.concat([s1,s2,s3])
Out[15]:
a 0
b 1
c 2
d 3
e 4
f 5
g 6
dtype: int64
默认情况下,concat是在axis=0上工作的,也就是按照行的方式进行拼接,设置axis=1就可以按照列的方式进行拼接。
In [16]: pd.concat([s1,s2,s3],axis=1)
Out[16]:
0 1 2
a 0.0 NaN NaN
b 1.0 NaN NaN
c NaN 2.0 NaN
d NaN 3.0 NaN
e NaN 4.0 NaN
f NaN NaN 5.0
g NaN NaN 6.0
我们还可以通过传入join=’inner’的方式取得并集
In [17]: s4=pd.concat([s1*5,s3])
In [18]: s4
Out[18]:
a 0
b 5
f 5
g 6
dtype: int64
In [19]: s1
Out[19]:
a 0
b 1
dtype: int64
In [20]: pd.concat([s1,s4],axis=1)
Out[20]:
0 1
a 0.0 0
b 1.0 5
f NaN 5
g NaN 6
In [21]: pd.concat([s1,s4],axis=1,join=\'inner\')
Out[21]:
0 1
a 0 0
b 1 5
前面在合并s1,s2,s3的时候得到的结果是
a 0
b 1
c 2
d 3
e 4
f 5
g 6
如果想层次化分层的话,可以通过设置key值来设置层次化索引
In [22]: result=pd.concat([s1,s2,s3],keys=[\'one\',\'two\',\'thress\'])
In [23]: result
Out[23]:
one a 0
b 1
two c 2
d 3
e 4
thress f 5
g 6
dtype: int64
In [25]: result=pd.concat([s1,s2,s3],axis=1,keys=[\'one\',\'two\',\'thress\'])
In [26]: result
Out[26]:
one two thress
a 0.0 NaN NaN
b 1.0 NaN NaN
c NaN 2.0 NaN
d NaN 3.0 NaN
e NaN 4.0 NaN
f NaN NaN 5.0
g NaN NaN 6.0
同样的使用方式对与DataFrame也是一样的。
concat函数的参数如下
重塑和轴向旋转
在线性代数中我们有转置的操作。在pandas中我们也可以进行类似的操作
stack:将数据的列旋转为行
unstack:将数据的行旋转为列
In [27]: data=DataFrame(np.arange(6).reshape((2,3)),index=pd.Index([\'Ohio\',\'Colo
...: rado\'],name=\'state\'),columns=pd.Index([\'one\',\'two\',\'three\'],name=\'numbe
...: r\'))
In [28]: data
Out[28]:
number one two three
state
Ohio 0 1 2
Colorado 3 4 5
In [29]: result=data.stack()
In [30]: result
Out[30]:
state number
Ohio one 0
two 1
three 2
Colorado one 3
two 4
three 5
dtype: int64
In [31]: result.unstack()
Out[31]:
number one two three
state
Ohio 0 1 2
Colorado 3 4 5
由于我们分别建立了行和列的索引,分别是state和number,因此我们可以指定索引来进行对应的转换
In [33]: result.unstack(\'state\')
Out[33]:
state Ohio Colorado
number
one 0 3
two 1 4
three 2 5
In [34]: result.unstack(\'number\')
Out[34]:
number one two three
state
Ohio 0 1 2
Colorado 3 4 5
如果不是所有的数据都在索引中能找到的话,则unstack操作会引入缺失的数据
In [35]: s1=Series([0,1,2,3],index=[\'a\',\'b\',\'c\',\'d\'])
In [38]: s2=Series([4,5,6],index=[\'c\',\'d\',\'e\'])
In [40]: data=pd.concat([s1,s2],keys=[\'one\',\'two\'])
In [41]: data
Out[41]:
one a 0
b 1
c 2
d 3
two c 4
d 5
e 6
dtype: int64
In [43]: data.unstack()
Out[43]:
a b c d e
one 0.0 1.0 2.0 3.0 NaN
two NaN NaN 4.0 5.0 6.0
以上是关于python数据分析之:数据清理,转换,合并,重塑的主要内容,如果未能解决你的问题,请参考以下文章