数据合并

层次化索引

层次化索引让你能在一个轴上拥有多个索引级别。
层次化索引我个人理解是对索引进行了分组,比方说一部分数据是今年的,一部分数据是明年的,可通过层次化索引进行切块以方便后续选取数据

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在右边没有相同的所以只有一个。

WechatIMG32.png

不同的连接类型:
WechatIMG33.png