python - Pandas:根据除一行之外的其他多级列对最里面的列进行分组排序

标签 python python-3.x pandas dataframe sorting

这是我的 previous question 的扩展:

考虑下面的df:

In [68]: df = pd.DataFrame({'A': ['a'] * 11,
    ...:                'B': ['b'] * 11,
    ...:                'C': ['C1', 'C1', 'C2','C1', 'C3', 'C3', 'C2', 'C3', 'C3', 'C2', 'C2'],
    ...:                'D': ['D1', 'D2', 'D1', 'D3', 'D3', 'D2', 'D4', 'D4', 'D1', 'D2', 'D3'],
    ...:                'E': [{'value': '4', 'percentage': None}, {'value': 5, 'percentage': None}, {'value': 12, 'percentage': None}, {'value': 9, 'percentage': None}, {'value': '12', 'percentage': None}, {'value': 'N/A', 'percentage': None}, {}, {'valu
    ...: e': 24, 'percentage': None}, {'value': 12, 'percentage': None}, {'value': 33, 'percentage': None}, {'value': 11, 'percentage': None}]})
    ...: 

上面 df 的透视:

In [69]: x = df.pivot(['B', 'C', 'D'], 'A', ['E'])

In [70]: x
Out[70]: 
                                            E
A                                           a
B C  D                                       
b C1 D1    {'value': '4', 'percentage': None}
     D2      {'value': 5, 'percentage': None}
     D3      {'value': 9, 'percentage': None}
  C2 D1     {'value': 12, 'percentage': None}
     D2     {'value': 33, 'percentage': None}
     D3     {'value': 11, 'percentage': None}
     D4                                    {}
  C3 D1     {'value': 12, 'percentage': None}
     D2  {'value': 'N/A', 'percentage': None}
     D3   {'value': '12', 'percentage': None}
     D4     {'value': 24, 'percentage': None}

我想根据索引为 (E) 的多级列,对每组外层列 B 和 C 的最内层列 D 进行排序, a)asc/desc 顺序基于字典中的 value 键。

但是,对于每个组,都会有一行包含所有其他行的值。无论排序顺序如何(升序或降序),我总是需要将该行保留在最后。

desc情况下的预期输出:

Out[70]: 
                                            E
A                                           a
B C  D                                       
b C1 D2      {'value': 5, 'percentage': None}
     D1    {'value': '4', 'percentage': None}
     D3      {'value': 9, 'percentage': None}
  C2 D1     {'value': 12, 'percentage': None}
     D3     {'value': 11, 'percentage': None}
     D4                                    {}
     D2     {'value': 33, 'percentage': None}
  C3 D1     {'value': 12, 'percentage': None}
     D3   {'value': '12', 'percentage': None}
     D2  {'value': 'N/A', 'percentage': None}
     D4     {'value': 24, 'percentage': None}

asc情况下的预期输出:

Out[70]: 
                                            E
A                                           a
B C  D                                       
b C1 D1    {'value': '4', 'percentage': None}
     D2      {'value': 5, 'percentage': None}
     D3      {'value': 9, 'percentage': None}
  C2 D3     {'value': 11, 'percentage': None}
     D1     {'value': 12, 'percentage': None}
     D4                                    {}
     D2     {'value': 33, 'percentage': None}
  C3 D1     {'value': 12, 'percentage': None}
     D3   {'value': '12', 'percentage': None}
     D2  {'value': 'N/A', 'percentage': None}
     D4     {'value': 24, 'percentage': None}

最佳答案

使用辅助列进行排序的解决方案 - 首先通过 Series.str.get转换为数字列和 to_numeric然后创建另一列比较每组的 bool 值最大值:

lvls = list(x.index.names[:-1])
print (lvls)
['B', 'C']

x[('tmp', 'tmp')] = pd.to_numeric(x[('E','a')].str.get('value'), errors='coerce')

x[('max','tmp')] = x.groupby(lvls)[[('tmp','tmp')]].transform('max') == x[[('tmp','tmp')]]

升序参数中的所有值为True,默认值:

x1 = x.sort_values(lvls + [('max','tmp'), ('tmp','tmp')])
print (x1)
                                            E   tmp    max
A                                           a   tmp    tmp
B C  D                                                    
b C1 D1    {'value': '4', 'percentage': None}   4.0  False
     D2      {'value': 5, 'percentage': None}   5.0  False
     D3      {'value': 9, 'percentage': None}   9.0   True
  C2 D3     {'value': 11, 'percentage': None}  11.0  False
     D1     {'value': 12, 'percentage': None}  12.0  False
     D4                                    {}   NaN  False
     D2     {'value': 33, 'percentage': None}  33.0   True
  C3 D1     {'value': 12, 'percentage': None}  12.0  False
     D3   {'value': '12', 'percentage': None}  12.0  False
     D2  {'value': 'N/A', 'percentage': None}   NaN  False
     D4     {'value': 24, 'percentage': None}  24.0   True
     

这里将最后的True更改为False:

x2 = x.sort_values(lvls + [('max','tmp'), ('tmp','tmp')],
                   ascending=[True] * len(lvls) + [True, False])
print (x2)

                                            E   tmp    max
A                                           a   tmp    tmp
B C  D                                                    
b C1 D2      {'value': 5, 'percentage': None}   5.0  False
     D1    {'value': '4', 'percentage': None}   4.0  False
     D3      {'value': 9, 'percentage': None}   9.0   True
  C2 D1     {'value': 12, 'percentage': None}  12.0  False
     D3     {'value': 11, 'percentage': None}  11.0  False
     D4                                    {}   NaN  False
     D2     {'value': 33, 'percentage': None}  33.0   True
  C3 D1     {'value': 12, 'percentage': None}  12.0  False
     D3   {'value': '12', 'percentage': None}  12.0  False
     D2  {'value': 'N/A', 'percentage': None}   NaN  False
     D4     {'value': 24, 'percentage': None}  24.0   True
     

最后删除辅助列:

x1 = x1.drop([('max','tmp'), ('tmp','tmp')], axis=1)
x2 = x2.drop([('max','tmp'), ('tmp','tmp')], axis=1)

关于python - Pandas:根据除一行之外的其他多级列对最里面的列进行分组排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65200527/

相关文章:

Python count() 传递 char 类型的数字时出现类型错误

python - 在散点图的工具提示中为每个气泡显示一个标签 (Matplotlib)

python-3.x - 如何将带有前导零的数据从 Pandas 导出到 CSV 并保留 csv 中的前导零

不同 DataFrame 并排的 Pandas 箱线图

python - 如何使用子流程模块正确地与流程交互

python - 在对象实例上使用装饰器(或其他一些模式)来生成类

python - 尝试将 csv 的第 1-10 行移动到 JSON 文件。我好像只得到了第10行

python - 从另一个具有不同索引的数据框中添加新列到 pandas 数据框中

python - 在线程中运行 bash 脚本不阻塞主循环

python - 在 Python 3 中尾随小数点 >= 0.5 时,math.ceil() 和 round() 之间的算法有什么区别?