数据透视表中每个级别的小计
Posted
技术标签:
【中文标题】数据透视表中每个级别的小计【英文标题】:Subtotal for each level in Pivot table 【发布时间】:2019-02-16 09:47:06 【问题描述】:我正在尝试创建一个数据透视表,除了一般总计之外,每个行级别之间还有一个小计。
我创建了我的 df。
import pandas as pd
df = pd.DataFrame(
np.array([['SOUTH AMERICA', 'BRAZIL', 'SP', 500],
['SOUTH AMERICA', 'BRAZIL', 'RJ', 200],
['SOUTH AMERICA', 'BRAZIL', 'MG', 150],
['SOUTH AMERICA', 'ARGENTINA', 'BA', 180],
['SOUTH AMERICA', 'ARGENTINA', 'CO', 300],
['EUROPE', 'SPAIN', 'MA', 400],
['EUROPE', 'SPAIN', 'BA', 110],
['EUROPE', 'FRANCE', 'PA', 320],
['EUROPE', 'FRANCE', 'CA', 100],
['EUROPE', 'FRANCE', 'LY', 80]], dtype=object),
columns=["CONTINENT", "COUNTRY","LOCATION","POPULATION"]
)
之后我创建了如下所示的数据透视表
table = pd.pivot_table(df, values=['POPULATION'], index=['CONTINENT', 'COUNTRY', 'LOCATION'], fill_value=0, aggfunc=np.sum, dropna=True)
table
为了做小计,我开始总结 CONTINENT 级别
tab_tots = table.groupby(level='CONTINENT').sum()
tab_tots.index = [tab_tots.index, ['Total'] * len(tab_tots)]
并与我的第一个枢轴连接以获得小计。
pd.concat([table, tab_tots]).sort_index()
得到它:
我怎样才能像第一个表一样获得按级别分隔的值?
我没有找到办法。
【问题讨论】:
看看这个 SO 帖子***.com/a/52209189/6361531。 【参考方案1】:使用margins=True
,并且需要更改您的pivot
index
和columns
的一点点。
newdf=pd.pivot_table(df, index=['CONTINENT'],values=['POPULATION'], columns=[ 'COUNTRY', 'LOCATION'], aggfunc=np.sum, dropna=True,margins=True)
newdf.drop('All').stack([1,2])
Out[132]:
POPULATION
CONTINENT COUNTRY LOCATION
EUROPE All 1010.0
FRANCE CA 100.0
LY 80.0
PA 320.0
SPAIN BA 110.0
MA 400.0
SOUTH AMERICA ARGENTINA BA 180.0
CO 300.0
All 1330.0
BRAZIL MG 150.0
RJ 200.0
SP 500.0
【讨论】:
【参考方案2】:IIUC:
contotal = table.groupby(level=0).sum().assign(COUNTRY='TOTAL', LOCATION='').set_index(['COUNTRY','LOCATION'], append=True)
coutotal = table.groupby(level=[0,1]).sum().assign(LOCATION='TOTAL').set_index(['LOCATION'], append=True)
df_out = (pd.concat([table,contotal,coutotal]).sort_index())
df_out
输出:
POPULATION
CONTINENT COUNTRY LOCATION
EUROPE FRANCE CA 100
LY 80
PA 320
TOTAL 500
SPAIN BA 110
MA 400
TOTAL 510
TOTAL 1010
SOUTH AMERICA ARGENTINA BA 180
CO 300
TOTAL 480
BRAZIL MG 150
RJ 200
SP 500
TOTAL 850
TOTAL 1330
【讨论】:
所有其他方式都可以进行一些自定义。但对我来说这是最客观和正确的答案,完美的谢谢你!【参考方案3】:你想做这样的事情
tab_tots.index = [tab_tots.index, ['Total'] * len(tab_tots), [''] * len(tab_tots)]
这给出了我认为你追求的以下内容
In [277]: pd.concat([table, tab_tots]).sort_index()
Out[277]:
POPULATION
CONTINENT COUNTRY LOCATION
EUROPE FRANCE CA 100
LY 80
PA 320
SPAIN BA 110
MA 400
Total 1010
SOUTH AMERICA ARGENTINA BA 180
CO 300
BRAZIL MG 150
RJ 200
SP 500
Total 1330
请注意,虽然这解决了您的问题,但它在风格上并不是好的编程。您的总和级别的逻辑不一致。
这对于 UI 界面来说是有意义的,但如果您正在使用数据,也许使用它会更好
tab_tots.index = [tab_tots.index, ['All'] * len(tab_tots), ['All'] * len(tab_tots)]
这遵循 SQL 表逻辑,会给你
In [289]: pd.concat([table, tab_tots]).sort_index()
Out[289]:
POPULATION
CONTINENT COUNTRY LOCATION
EUROPE All All 1010
FRANCE CA 100
LY 80
PA 320
SPAIN BA 110
MA 400
SOUTH AMERICA ARGENTINA BA 180
CO 300
All All 1330
BRAZIL MG 150
RJ 200
SP 500
【讨论】:
非常感谢亚历山大!但是,如果我也想要 COUNTRY 的小计,我该怎么做呢?tab_tots = table.groupby(level=['CONTINENT', 'COUNTRY']).sum()
我已经尝试不重做您的代码。而是以您自己的方法选择需要更改的单件,以便您更好地理解它。让我知道这是否有帮助以上是关于数据透视表中每个级别的小计的主要内容,如果未能解决你的问题,请参考以下文章