Pandas透视表多层排序

bvhaajcl  于 2023-04-18  发布在  其他
关注(0)|答案(1)|浏览(144)

我给了df:(已更新):

import pandas as pd
import numpy as np
df = pd.DataFrame({"A": ["foo", "foo", "foo", "foo", "foo",
                         "bar", "bar", "bar", "bar","zz","zz"],
                  "B": ["one", "one", "one", "two", "two",
                         "one", "one", "two", "two","xy","zz"],
                   "Name":["Peter", "Amy", "Brian", "Amy", "Amy",
                         "Peter", "Brian", "Peter", "Brian","Brian","Brian"],
                  "Year": [2019, 2019, 2019, 2019,
                         2019, 2019, 2020, 2020,
                          2020,2019,2020],
                  "Values": [20, 4, 20, 5, 6, 6, 8, 9, 9,10,5]})
df_pivot = pd.pivot_table(df, values='Values', index=['Name','A', 'B'],
                    columns=['Year'], aggfunc=np.sum, fill_value=0, margins=True, margins_name="Totals")

一旦我以我喜欢的方式旋转它,它看起来像这样:

Year            2019  2020  Totals
Name   A   B                      
Amy    foo one     4     0       4
           two    11     0      11
Brian  bar one     0     8       8
           two     0     9       9
       foo one    20     0      20
       zz  xy     10     0      10
           zz      0     5       5
Peter  bar one     6     0       6
           two     0     9       9
       foo one    20     0      20
Totals            71    31     102

现在“有趣”的部分开始了。
我想这个df透视表是排序的所有索引列从左到右的基础上总和的价值观。
让我解释一下。
首先,我想按每个名称的“Totals”降序排列“Name”列,因此我将计算Amy = 15,Brian = 52,Peter= 35的总和。由此我知道第一列应该排序Brian/Peter/Amy。
现在我对第二列“A”做同样的操作,但第一列“Name”是固定的。
也就是说,对于名字Brian(在上面),我现在计算列“A”的总数(我想看看foo/bar/zz是否应该是第一个),因此我计算出Brian-Foo等于20,Brian-bar等于8+9,Brian-zz等于15,因此我们希望在第二列中Brian的Foo是第一个......其余索引列也是如此。
输出应该如下所示:

Year            2019  2020  Totals
Name   A   B                      
Brian  foo one    20     0      20 
       bar two     0     9       9
           one     0     8       8
       zz  xy     10     0      10
           zz      0     5       5
Peter  foo one    20     0      20
       bar two     0     9       9
           one     6     0       6
Amy    foo two    11     0      11
           one     4     0       4
Totals            71    31     102

长话短说,首先,我想根据该列的项目总数对第一列进行排序,然后我想修复它,然后我想对该列的项目进行第二列排序,但按第一次排序等分组。
你能告诉我怎么做吗?我很感激你的帮助!
谢谢帕维尔

bgtovc5b

bgtovc5b1#

你可以使用groupby.transform来获取名字的和,然后用它排序:

df_pivot = (df_pivot.iloc[:-1]
              .assign(sort=lambda x: x['Totals'].groupby(level=0).transform('sum'))
              .sort_values(['sort','Name','Totals'], 
                           ascending=[False,True,False], kind='mergesort')
              .drop('sort', axis=1)
              .append(df_pivot.iloc[-1])
           )

输出:

Year            2019  2020  Totals
Name   A   B                      
Brian  foo one    20     0      20
       bar two     0     9       9
           one     0     8       8
Peter  foo one    20     0      20
       bar two     0     9       9
           one     6     0       6
Amy    foo two    11     0      11
           one     4     0       4
Totals            61    26      87

相关问题