层次化索引
层次化索引让你能在一个轴上拥有多个索引级别。
层次化索引我个人理解是对索引进行了分组,比方说一部分数据是今年的,一部分数据是明年的,可通过层次化索引进行切块以方便后续选取数据
In [263]: data = Series(np.random.randn(10), index=[['2010','2010','2010','2011','2011','2011','2012','2012','2013','2013'],[
...: 1, 2, 3, 1, 2, 3, 1, 2, 2, 3]]) # 这种形式叫做带有```MultiIndex```索引的格式化输出形式。
In [264]: data
Out[264]:
2010 1 1.739760
2 -1.685753
3 0.046604
2011 1 -0.580861
2 -1.848230
3 0.148327
2012 1 0.552871
2 1.347311
2013 2 -0.555054
3 0.601366
dtype: float64
选取分好组的数据:
In [265]: data['2010']
Out[265]:
1 1.739760
2 -1.685753
3 0.046604
dtype: float64
In [267]: data.loc[['2010','2011']]
Out[267]:
2010 1 1.739760
2 -1.685753
3 0.046604
2011 1 -0.580861
2 -1.848230
3 0.148327
dtype: float64
重塑层次化索引
重塑相当于是把一个带有层次化索引的Series
转换成了DataFrame
,或者把DataFrame
转换成带有层次化索引的Series
。
In [269]: data.unstack()
Out[269]:
1 2 3
2010 1.739760 -1.685753 0.046604
2011 -0.580861 -1.848230 0.148327
2012 0.552871 1.347311 NaN
2013 NaN -0.555054 0.601366
In [280]: data.unstack().stack()
Out[280]:
2010 1 1.739760
2 -1.685753
3 0.046604
2011 1 -0.580861
2 -1.848230
3 0.148327
2012 1 0.552871
2 1.347311
2013 2 -0.555054
3 0.601366
dtype: float64
对于DataFrame来说,每条轴都可以有分层索引
In [36]: frame = DataFrame(np.arange(12).reshape(4,3),index=[['a','a','b','b'],[1,2,1,2]],columns=[
...: ['Ohio','Ohio','Colorado'],['Green','Red','Green']])
In [37]: frame
Out[37]:
Ohio Colorado
Green Red Green
a 1 0 1 2
2 3 4 5
b 1 6 7 8
2 9 10 11
有了分部的列索引,选取列分组会十分轻松:
In [38]: frame['Ohio']
Out[38]:
Green Red
a 1 0 1
2 3 4
b 1 6 7
2 9 10
数据库DataFrame合并:
In [70]: df1 = DataFrame({'key':['b','b','a','c','a','a','b'],'data1':range(7)})
In [71]: df2 = DataFrame({'key':['a','b','d'],'data2':range(3)})
In [72]: df1
Out[72]:
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 a 5
6 b 6
数据库DataFrame合并在未指定合并列的情况下会默认会将键名相同的列进行合并,如例子中的key
。合并之后会取两组数据中的交集,其他的会被清除。
当然我们也可以指定合并列
In [77]: pd.merge(df1,df2,on='key') #指定了key列为合并项
Out[77]:
key data1 data2
0 b 0 1
1 b 1 1
2 b 6 1
3 a 2 0
4 a 4 0
5 a 5 0
合并默认是交集,肯定也可以改为并集
In [82]: pd.merge(df1,df2, how='outer')
Out[82]:
key data1 data2
0 b 0.0 1.0
1 b 1.0 1.0
2 b 6.0 1.0
3 a 2.0 0.0
4 a 4.0 0.0
5 a 5.0 0.0
6 c 3.0 NaN
7 d NaN 2.0
除了交集与并集,还有左连接与右连接统称为多对多合并
多对多合并
In [83]: df1 = DataFrame({'key':['b','b','a','c','a','b'],'data1':range(6)})
In [84]: df2 = DataFrame({'key':['a','b','a','b','d'],'data2':range(5)})
In [85]: df1
Out[85]:
key data1
0 b 0
1 b 1
2 a 2
3 c 3
4 a 4
5 b 5
In [86]: df2
Out[86]:
key data2
0 a 0
1 b 1
2 a 2
3 b 3
4 d 4
因为多对多连接会产生行的笛卡尔积,所以结果会跟交集并集不同,类似于这样。
In [39]: df1 = DataFrame({'key':['b','b','a','c','a','b'],'data1':range(6)})
In [40]: df2 = DataFrame({'key':['a','b','a','b','d'],'data2':range(5)})
In [41]: pd.merge(df1,df2,on='key',how='left')
Out[41]:
key data1 data2
0 b 0 1.0
1 b 0 3.0
2 b 1 1.0
3 b 1 3.0
4 a 2 0.0
5 a 2 2.0
6 c 3 NaN
7 a 4 0.0
8 a 4 2.0
9 b 5 1.0
10 b 5 3.0
同样这里产生了笛卡尔积,它的合并规则如下图所示,由于how=left
,也就是data1
为主目标向data2
合并,图片中例举了b
这个键是如何合并的。左边有3个b
,右边有2个,左右相同的键进行一一合并后就产生了6个b
。同样a
就会产生4个,而c
在右边没有相同的所以只有一个。
不同的连接类型: