美文网首页
第08章 数据规整:聚合、合并和重塑

第08章 数据规整:聚合、合并和重塑

作者: AmaAnchor | 来源:发表于2019-03-27 12:54 被阅读0次

    ps:在pandas中,对索引的操作默认都为行索引

    层次化索引

    In [61]: data=pd.Series(np.random.randn(9),index=[['a','a','a','b','b','c','c','d','d'],[1,2,3,1,2,1,3,1,5]])
    
    In [62]: data
    Out[62]:
    a  1   -0.544257
       2    0.129334
       3   -0.169315
    b  1   -0.290376
       2   -0.134793
    c  1    1.854275
       3   -0.912308
    d  1   -0.246389
       5   -0.551807
    dtype: float64
    

    层次化索引在数据重塑和基于分组的操作(如透视表生成)

    将多级索引的Series转为DataFrame:unstack方法:

    In [63]: data.unstack()
    Out[63]:
              1         2         3         5
    a -0.544257  0.129334 -0.169315       NaN
    b -0.290376 -0.134793       NaN       NaN
    c  1.854275       NaN -0.912308       NaN
    d -0.246389       NaN       NaN -0.551807
    

    重排与分级排序

    交换索引级别

    frame.swaplevel(0,1,axis='columns')
    

    选择索引排序的级别

     frame.sort_index(level='key1')
    

    根据级别汇总统计

    In [109]: frame
    
    Out[109]:
    kind1     male    female
    kind2        e  e      u  u
    key1 key2
    a    1       5  6      2  8
         2       0  9      3  5
    b    1       0  3      7  7
         2       2  1      7  6
    
    In [110]: frame.sum(level='key1')
    
    Out[110]:
    kind1 male     female
    kind2    e   e      u   u
    key1
    a        5  15      5  13
    b        2   4     14  13
    

    使用DataFrame的列进行索引

    将列作为索引:

    In [118]: frame
    Out[118]:
       a  b    c  d
    0  0  7  one  0
    1  1  6  one  1
    2  2  5  one  2
    3  3  4  two  0
    4  4  3  two  1
    5  5  2  two  2
    6  6  1  two  3
    

    参数drop决定是否在原对象中保留索引列。(默认为True,不保留)

    In [119]: frame.set_index(['c','d'],drop=False)
    Out[119]:
           a  b    c  d
    c   d
    one 0  0  7  one  0
        1  1  6  one  1
        2  2  5  one  2
    two 0  3  4  two  0
        1  4  3  two  1
        2  5  2  two  2
        3  6  1  two  3
    

    与set_index相反:reset_index

    8.2 合并数据集

    pandas.merge:可根据一个或多个键将不同DataFrame中的行连接起来;相当于数据库的join操作
    pandas.concat:可以沿着一条轴将多个对象堆叠到一起。
    实例方法combine_first可以将重复数据拼接在一起,用一个对象中的值填充另一个对象中的缺失值。

    多对一

    连接两个表:pd.merge
    参数on默认为属性有重叠的列的列名
    列名相同

    In [135]: pd.merge(df1,df2,on='key')
    

    列名不同:分别指定参数left_on和参数right_on

    In [145]: df3
    Out[145]:
      lkey  data1
    0    b      0
    1    b      1
    2    a      2
    3    c      3
    4    a      4
    5    a      5
    6    b      6
    
    In [146]: df4
    Out[146]:
      rkey  data2
    0    a      0
    1    b      1
    2    d      2
    
    
    In [147]: pd.merge(df3,df4,left_on='lkey',right_on='rkey')
    
    Out[147]:
      lkey  data1 rkey  data2
    0    b      0    b      1
    1    b      1    b      1
    2    b      6    b      1
    3    a      2    a      0
    4    a      4    a      0
    5    a      5    a      0
    

    注意到:key值为c和的数据消失了
    这是因为默认情况下,merge做的是“内连接”;结果中的键是交集。其他方式还有"left"、"right"以及"outer"。外连接求取的是键的并集,组合了左连接和右连接的效果:
    修改参数how即可改变连接方式:(how的可选参数为:inner,outer,right,left)

    In [149]: pd.merge(df3,df4,left_on='lkey',right_on='rkey',how='outer')
    
    
      lkey  data1 rkey  data2
    0    b    0.0    b    1.0
    1    b    1.0    b    1.0
    2    b    6.0    b    1.0
    3    a    2.0    a    0.0
    4    a    4.0    a    0.0
    5    a    5.0    a    0.0
    6    c    3.0  NaN    NaN
    7  NaN    NaN    d    2.0
    

    多对多

    多对多产生的是行的笛卡儿积
    
    In [151]: df1
    Out[151]:
      key  data1
    0   b      0
    1   b      1
    2   a      2
    3   c      3
    4   a      4
    5   b      5
    
    In [152]: df2
    Out[152]:
      key  data2
    0   a      0
    1   b      1
    2   a      2
    3   b      3
    4   d      4
    
    In [153]: pd.merge(df1,df2,how='inner')
    
    Out[153]:
      key  data1  data2
    0   b      0      1
    1   b      0      3
    2   b      1      1
    3   b      1      3
    4   b      5      1
    5   b      5      3
    6   a      2      0
    7   a      2      2
    8   a      4      0
    9   a      4      2
    
    

    根据多个键进行合并:给on参数传入一个键列表:

    In [163]: pd.merge(left,right,on=['key1','key2'])
    
    Out[163]:
      key1 key2  lval  rval
    0  foo  one     1     4
    1  foo  one     1     5
    2  bar  one     3     6
    

    处理重复列名:merge的suffixes选项

    In [171]: pd.merge(left,right,on='key1',suffixes=['_left','_right'])
    
    Out[171]:
      key1 key2_left  lval key2_right  rval
    0  foo       one     1        one     4
    1  foo       one     1        one     5
    2  foo       two     2        one     4
    3  foo       two     2        one     5
    4  bar       one     3        one     6
    5  bar       one     3        two     7
    
    image.png image.png

    连接层次化索引的数据,以索引作为连接列:

    In [36]: righth
    Out[36]:
                 event1  event2
    Nevada 2001       0       1
           2000       2       3
    Ohio   2000       4       5
           2000       6       7
           2001       8       9
           2002      10      11
    
    In [37]: lefth
    Out[37]:
         key1  key2  data
    0    Ohio  2000   0.0
    1    Ohio  2001   1.0
    2    Ohio  2002   2.0
    3  Nevada  2001   3.0
    4  Nevada  2002   4.0
    

    要将索引作为连接列,即设置参数righ_index为True

    In [39]: pd.merge(lefth,righth,left_on=['key1','key2'],right_index=True,how='outer')
    Out[39]:
         key1  key2  data  event1  event2
    0    Ohio  2000   0.0     4.0     5.0
    0    Ohio  2000   0.0     6.0     7.0
    1    Ohio  2001   1.0     8.0     9.0
    2    Ohio  2002   2.0    10.0    11.0
    3  Nevada  2001   3.0     0.0     1.0
    4  Nevada  2002   4.0     NaN     NaN
    4  Nevada  2000   NaN     2.0     3.0
    
    

    当然可以同时使用双方的索引作为连接列

    In [46]: left2
    Out[46]:
       Ohio  Nevada
    a   1.0     2.0
    c   3.0     4.0
    e   5.0     6.0
    
    In [47]: right2
    Out[47]:
       Missouri  Alabama
    b       7.0      8.0
    c       9.0     10.0
    d      11.0     12.0
    e      13.0     14.0
    
    In [48]: pd.merge(left2,right2,left_index=True,right_index=True)
    Out[48]:
       Ohio  Nevada  Missouri  Alabama
    c   3.0     4.0       9.0     10.0
    e   5.0     6.0      13.0     14.0
    

    或者直接使用DataFrame对象的实例方法:join来直接实现索引合并

    left2.join(right2,how='outer')
    

    join方法支持连接多的DataFrame对象:

    In [56]: another
    Out[56]:
       New York  Oregon
    a       7.0     8.0
    c       9.0    10.0
    e      11.0    12.0
    f      16.0    17.0
    
    In [57]: left2.join([right2,another])
    Out[57]:
       Ohio  Nevada  Missouri  Alabama  New York  Oregon
    a   1.0     2.0       NaN      NaN       7.0     8.0
    c   3.0     4.0       9.0     10.0       9.0    10.0
    e   5.0     6.0      13.0     14.0      11.0    12.0
    

    轴向连接:np.concatenate 和pd.concat

    numpy的concatenate方法

    np.concatenate([arr,arr],axis=1)
    

    pandas的concat方法

    pd.concat([s1,s2,s3],axis=1)
    
    Out[103]:
         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
    
    In [89]: pd.concat([s1, s4], axis=1)
    Out[89]: 
         0  1
    a  0.0  0
    b  1.0  1
    f  NaN  5
    g  NaN  6
    
    In [90]: pd.concat([s1, s4], axis=1, join='inner')
    Out[90]: 
       0  1
    a  0  0
    b  1  1
    

    在连接轴上创建一个层次化索引:使用keys参数

    In [122]: pd.concat([s1,s2],keys=['key1','key2'])
    Out[122]:
    key1  a    0
          b    1
    key2  c    2
          d    3
          e    4
    dtype: int64
    

    该逻辑同样使用与DataFrame对象

    In [136]: pd.concat([df1,df2],axis=1,keys=['level1','level2'])
    
    Out[136]:
      level1     level2
         one two  three four
    a      0   1    5.0  6.0
    b      2   3    NaN  NaN
    c      4   5    7.0  8.0
    

    如果传入的是字典而不是列表,则字典的键就会作为keys的值

    In [141]: pd.concat({'level1':df1,'level2':df2},axis=1)
    
    Out[141]:
      level1     level2
         one two  three four
    a      0   1    5.0  6.0
    b      2   3    NaN  NaN
    c      4   5    7.0  8.0
    

    可以给层次索引命名

    In [22]: pd.concat([df1,df2],axis=1,keys=['level1','leve12'],names=['high','low'])
    
    Out[22]:
    high level1     leve12
    low     one two  three four
    a         0   1    5.0  6.0
    b         2   3    NaN  NaN
    c         4   5    7.0  8.0
    

    当待合并DataFrame的索引不包括任何东西,此时我们通常需要对行索引依次重新排序
    使用参数ignore_index=True

    In [28]: pd.concat([df1,df2],ignore_index=True)
    
    Out[28]:
              a         b         c         d
    0 -0.404371  0.343314  1.938941  1.078406
    1 -0.270911  0.500551  0.334860 -0.833356
    2  0.393762  1.439736 -0.115172 -0.085488
    3 -0.200651 -0.475177       NaN  0.157968
    4  0.115498  0.429316       NaN -0.717663
    

    合并重叠数据

    回顾np.where方法:相当于if-else

    In [69]: a
    Out[69]:
    f    NaN
    e    2.5
    d    NaN
    c    3.5
    b    4.5
    a    NaN
    dtype: float64
    
    In [70]: b
    Out[70]:
    f    0.0
    e    1.0
    d    2.0
    c    3.0
    b    4.0
    a    NaN
    dtype: float64
    

    实现了功能:a中空缺的数据用b中的数据去填补

    In [71]: np.where(a.isnull(),b,a)
    Out[71]: array([0. , 2.5, 2. , 3.5, 4.5, nan])
    

    Series对象也有类似的功能:Series.combine_first

    In [74]: a.combine_first(b)
    Out[74]:
    f    0.0
    e    2.5
    d    2.0
    c    3.5
    b    4.5
    a    NaN
    dtype: float64
    
    

    8.3 重塑和轴向旋转

    有许多用于重新排列表格型数据的基础运算。这些函数也称作重塑(reshape)或轴向旋转(pivot)运算。
    

    重塑层次化索引

    stack:将数据的列“旋转”为行。
    unstack:将数据的行“旋转”为列。

    In [90]: data
    Out[90]:
    number    one  two  three
    state
    Ohio        0    1      2
    Colorado    3    4      5
    
    In [92]: data.stack()
    Out[92]:
    state     number
    Ohio      one       0
              two       1
              three     2
    Colorado  one       3
              two       4
              three     5
    dtype: int32
    

    对于Series和DataFrame通过stack和unstack转换的理解:stack意为:堆叠。多级索引即是将索引进行了堆叠,所以用unstack即使之不堆叠,从而Series=》DataFrame。反之同理

    将“长格式”旋转为“宽格式”

    相关文章

      网友评论

          本文标题:第08章 数据规整:聚合、合并和重塑

          本文链接:https://www.haomeiwen.com/subject/bavtmqtx.html