Pandas:如何包含多个数据透视表的所有列和所有索引 table

Pandas: How to include all columns and all indexes for multiple pivot table

我正在尝试为来自以下数据框 (df) 的不同位置创建枢轴 tables:

Location Category Status Price
1 Furniture New 0
1 Furniture Old
2 Office Supplies New 0
1 Furniture New 0
1 Office Supplies New 0
1 Office Supplies Old 0

首先,我使用代码过滤了数据帧以分离位置 1 和 2:

df1 = df[df['Location'] == 1]

df2 = df[df['Location'] == 2]

接下来我使用了标准的 pandas pivot table 函数:

pd.pivot_table(df1, values='Price', index='Status', columns='Category', aggfunc=np.sum)

pd.pivot_table(df2, values='Price', index='Status', columns='Category', aggfunc=np.sum)

所以我有以下两个枢轴 table 作为输出:

位置 1:

Status Furniture Office Supplies
New 0 0
Old 0

位置 2:

Status Office Supplies
New 0

但是,我希望位置 2 的枢轴 table 包含所有可能的类别和状态,如果不存在则为 0。总而言之,我想要位置 2 的以下枢轴 table:

位置 2:

Status Furniture Office Supplies
New [=18=] 0
Old [=18=] [=18=]

我已经遍历了 pivot_table() 函数的所有选项,但到目前为止还没有找到解决这个问题的方法。

您可以在拆分 Location 之前创建枢轴 table。

对于pd.pivot_table

  • 设置索引 index=['Location', 'Status']
  • 传递参数 dropna=False 以允许所有类别显示所有 Location 和所有 Status,即使是空的。 (默认是隐藏空条目)。
  • 传递参数 fill_value=0 以将 NaN 值填充为 0

然后通过.loc从支点table定位Location,如下:

df_out = pd.pivot_table(df, 
                        values='Price', 
                        index=['Location', 'Status'], 
                        columns='Category', 
                        aggfunc=np.sum, 
                        dropna=False, 
                        fill_value=0)

结果:

print(df_out)

Category         Furniture  Office Supplies
Location Status                            
1        New           200              300
         Old            50              150
2        New             0              200
         Old             0                0

那么,为了得到Location2的枢轴table,可以使用.loc,如下:

df2 = df_out.loc[2]

输出:

print(df2)

Category  Furniture  Office Supplies
Status                              
New               0              200
Old               0                0

编辑(添加总计和小计)

如果您还想包括 总计(对于所有 Location)和 小计(对于每个 Location),你也可以这样做,如下:

对于pd.pivot_table

  • 传递参数 margins=Truemargins_name='Total' 来设置 Total 的边距(所有 Location 的总计)
  • pd.pivot_table 之后链接命令 fillna(0, downcast='infer')。这是为了处理 pd.pivot_table 故障 / 错误 保证金总额仍将显示 NaN 空条目(例如 Location=2 Status='Old' 在这种情况下)即使指定了 fill_value=0 参数。
df_out = pd.pivot_table(df, 
                        values='Price', 
                        index=['Location', 'Status'], 
                        columns='Category', 
                        aggfunc=np.sum, 
                        dropna=False, 
                        fill_value=0,
                        margins=True,
                        margins_name='Total'
                        ).fillna(0, downcast='infer')

结果

print(df_out)

Category         Furniture  Office Supplies  Total
Location Status                                   
1        New           200              300    500
         Old            50              150    200
2        New             0              200    200
         Old             0                0      0
Total                  250              650    900

然后,要添加 小计(对于每个 Location),我们进一步使用:

(pd.concat([df_out, 
            df_out.query('Location != "Total"')
                  .groupby(level=0).sum()
                  .assign(Status='Sub-total')
                  .set_index('Status', append=True)])
   .sort_index())

结果:

Category            Furniture  Office Supplies  Total
Location Status                                      
1        New              200              300    500
         Old               50              150    200
         Sub-total        250              450    700
2        New                0              200    200
         Old                0                0      0
         Sub-total          0              200    200
Total                     250              650    900