【问题标题】:Pandas dataframe with multiindex column - merge levels具有多索引列的 Pandas 数据框 - 合并级别
【发布时间】:2014-08-09 00:42:03
【问题描述】:

我有一个数据框grouped,其多索引列如下:

import pandas as pd
codes = ["one","two","three"];
colours = ["black", "white"];
textures = ["soft", "hard"];
N= 100 # length of the dataframe
df = pd.DataFrame({ 'id' : range(1,N+1),
                    'weeks_elapsed' : [random.choice(range(1,25)) for i in range(1,N+1)],
                    'code' : [random.choice(codes) for i in range(1,N+1)],
                    'colour': [random.choice(colours) for i in range(1,N+1)],
                    'texture': [random.choice(textures) for i in range(1,N+1)],
                    'size': [random.randint(1,100) for i in range(1,N+1)],
                    'scaled_size': [random.randint(100,1000) for i in range(1,N+1)]
                   },  columns= ['id', 'weeks_elapsed', 'code','colour', 'texture', 'size', 'scaled_size'])
grouped = df.groupby(['code', 'colour']).agg( {'size': [np.sum, np.average, np.size, pd.Series.idxmax],'scaled_size': [np.sum, np.average, np.size, pd.Series.idxmax]}).reset_index()

>> grouped
    code colour     size                           scaled_size                         
                    sum    average  size  idxmax            sum    average  size  idxmax
0    one  black    1031  60.647059    17      81     185.153944  10.891408    17      47
1    one  white     481  37.000000    13      53     204.139249  15.703019    13      53
2  three  black     822  48.352941    17       6     123.269405   7.251141    17      31
3  three  white    1614  57.642857    28      50     285.638337  10.201369    28      37
4    two  black     523  58.111111     9      85      80.908912   8.989879     9      88
5    two  white     669  41.812500    16      78      82.098870   5.131179    16      78
[6 rows x 10 columns]

如何将列索引级别展平/合并为:“Level1|Level2”,例如size|sumscaled_size|sum。等等?如果这不可能,有没有办法像我在上面所做的那样groupby() 而无需创建多索引列?

【问题讨论】:

  • 这只是我的看法,我觉得 scott's 比公认的要好。

标签: python pandas multi-index


【解决方案1】:

可能有更好的方法,更 Pythonic 的方法来展平 MultiIndex 列。

1。使用 map 和 join 字符串列标题:

grouped.columns = grouped.columns.map('|'.join).str.strip('|')

print(grouped)

输出:

   code  colour   size|sum  size|average  size|size  size|idxmax  \
0    one   black       862     53.875000         16           14   
1    one   white       554     46.166667         12           18   
2  three   black       842     49.529412         17           90   
3  three   white       740     56.923077         13           97   
4    two   black      1541     61.640000         25           50   

   scaled_size|sum  scaled_size|average  scaled_size|size  scaled_size|idxmax  
0             6980           436.250000                16                  77  
1             6101           508.416667                12                  13  
2             7889           464.058824                17                  64  
3             6329           486.846154                13                  73  
4            12809           512.360000                25                  23  

2。对具有数字数据类型的列标题使用带格式的映射。

grouped.columns = grouped.columns.map('{0[0]}|{0[1]}'.format) 

输出:

   code| colour|  size|sum  size|average  size|size  size|idxmax  \
0    one   black       734     52.428571         14           30   
1    one   white      1110     65.294118         17           88   
2  three   black       930     51.666667         18            3   
3  three   white      1140     51.818182         22           20   
4    two   black       656     38.588235         17           77   
5    two   white       704     58.666667         12           17   

   scaled_size|sum  scaled_size|average  scaled_size|size  scaled_size|idxmax  
0             8229           587.785714                14                  57  
1             8781           516.529412                17                  73  
2            10743           596.833333                18                  21  
3            10240           465.454545                22                  26  
4             9982           587.176471                17                  16  
5             6537           544.750000                12                  49 

3。在 Python 3.6+ 中使用带有 f-string 的列表推导:

grouped.columns = [f'{i}|{j}' if j != '' else f'{i}' for i,j in grouped.columns]

输出:

    code colour  size|sum  size|average  size|size  size|idxmax  \
0    one  black      1003     43.608696         23           76   
1    one  white      1255     59.761905         21           66   
2  three  black       777     45.705882         17           39   
3  three  white       630     52.500000         12           23   
4    two  black       823     54.866667         15           33   
5    two  white       491     40.916667         12           64   

   scaled_size|sum  scaled_size|average  scaled_size|size  scaled_size|idxmax  
0            12532           544.869565                23                  27  
1            13223           629.666667                21                  13  
2             8615           506.764706                17                  92  
3             6101           508.416667                12                  43  
4             7661           510.733333                15                  42  
5             6143           511.916667                12                  49  

【讨论】:

  • 当你有数字列时它不起作用MultiIndex(levels=[[u'col_a', u'col_b', u'col_c'], [7950230.0, 12304568.0]], labels=[[0, 0, 1], [0, 1, 1]], names=[lev, sublev'])它返回TypeError: sequence item 1: expected string, float found
  • 简要更新,至少从 v0.23 开始,您可以使用 set_axis 方法:renamed = df.set_axis(['|'.join(c) for c in df.columns], axis='columns', inplace=False)
  • 嗨,伙计,调整一下grouped.columns.map('|'.join).str.strip('|'),顺便说一句,我认为这应该是公认的答案
  • 这是一个很好的解决方案!详细而彻底。
  • @ThePyGuy 谢谢!
【解决方案2】:

您可以随时更改列:

grouped.columns = ['%s%s' % (a, '|%s' % b if b else '') for a, b in grouped.columns]

【讨论】:

  • 如果级别 1 中的一列等于0,那么上面的表达式将在这里忽略它:b if b else ''。相反,我使用了b != '',所以grouped.columns = ['%s%s' % (a, '|%s' % b if b != '' else '') for a, b in grouped.columns]。这在使用 groupby 枚举从 0 开始的数字的列之后可能很有用。
  • Nones 会有问题,所以你必须做if (b == 0 or b),但仍然是一个很好的电话
  • @acusher,你说得对,虽然 if b is not None 应该是简单的表达方式......
【解决方案3】:

根据 Scott Boston 的回答, 很少更新(它将适用于 2 级或更多级别的列):

temp.columns.map(lambda x: '|'.join([str(i) for i in x]))

谢谢你,波士顿!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 2016-10-28
    • 1970-01-01
    • 1970-01-01
    • 2021-09-25
    • 2020-02-22
    相关资源
    最近更新 更多