如何在pandas中创建sum行和sum列?

Way*_*ner 24 python pandas

我正在通过可汗学院的统计学课程作为我大学时代的一些复习,并且作为一种让我快速掌握大熊猫和其他科学Python的方法.

我有一张来自可汗学院的桌子:

             | Undergraduate | Graduate | Total
-------------+---------------+----------+------
Straight A's |           240 |       60 |   300
-------------+---------------+----------+------
Not          |         3,760 |      440 | 4,200
-------------+---------------+----------+------
Total        |         4,000 |      500 | 4,500
Run Code Online (Sandbox Code Playgroud)

我想用pandas重新创建这个表.当然,我可以使用类似的东西创建一个DataFrame

"Graduate": {...},
"Undergraduate": {...},
"Total": {...},
Run Code Online (Sandbox Code Playgroud)

但这似乎是一种天真的方法,既快速挫败,又不是真正可扩展的.

我有这样的非总计部分:

df = pd.DataFrame(
    {
        "Undergraduate": {"Straight A's": 240, "Not": 3_760},
        "Graduate": {"Straight A's": 60, "Not": 440},
    }
)
df
Run Code Online (Sandbox Code Playgroud)

我一直在寻找并发现了一些很有前景的东西,比如:

df['Total'] = df.sum(axis=1)
Run Code Online (Sandbox Code Playgroud)

但我没有发现任何非常优雅的东西.

我确实找到了crosstab看起来应该做我想要的功能,但似乎为了做到这一点,我必须为所有这些值创建一个由1/0组成的数据帧,这看起来很愚蠢,因为我已经已经有一个聚合.

我发现一些方法似乎手动构建一个新的总计行,但似乎应该有一个更好的方法,如:

totals(df, rows=True, columns=True)
Run Code Online (Sandbox Code Playgroud)

或者其他的东西.

这是否存在于熊猫中,还是我必须拼凑自己的方法?

Arc*_*hie 26

或者分两步,使用.sum()您建议的功能(也可能更具可读性):

import pandas as pd

df = pd.DataFrame( {"Undergraduate": {"Straight A's": 240, "Not": 3_760},"Graduate": {"Straight A's": 60, "Not": 440},})

#Total sum per column: 
df.loc['Total',:]= df.sum(axis=0)

#Total sum per row: 
df.loc[:,'Total'] = df.sum(axis=1)
Run Code Online (Sandbox Code Playgroud)

输出:

              Graduate  Undergraduate  Total
Not                440           3760   4200
Straight A's        60            240    300
Total              500           4000   4500
Run Code Online (Sandbox Code Playgroud)

  • @WayneWerner那是因为这是一个到位的操作.看来你已经运行了两次 (6认同)

piR*_*red 11

appendassign

这个答案的要点是提供一个在线而不是一个到位的解决方案.

append

append用来堆叠SeriesDataFrame垂直.它还创造了一个copy我可以继续链.

assign

assign用来添加一个列.但是,DataFrame我正在研究的是在下层空间之间.所以我lambdaassign参数中使用a 来告诉Pandas它将它应用于调用DataFrame.


df.append(df.sum().rename('Total')).assign(Total=lambda d: d.sum(1))

              Graduate  Undergraduate  Total
Not                440           3760   4200
Straight A's        60            240    300
Total              500           4000   4500
Run Code Online (Sandbox Code Playgroud)

有趣的选择

使用dropwith errors='ignore'来摆脱潜在的预先存在的Total行和列.

此外,仍然排队.

def tc(d):
  return d.assign(Total=d.drop('Total', errors='ignore', axis=1).sum(1))

df.pipe(tc).T.pipe(tc).T

              Graduate  Undergraduate  Total
Not                440           3760   4200
Straight A's        60            240    300
Total              500           4000   4500
Run Code Online (Sandbox Code Playgroud)


WeN*_*Ben 5

从使用的原始数据crosstab,如果只是基于您的输入,您只需要melt之前crosstab

s=df.reset_index().melt('index')
pd.crosstab(index=s['index'],columns=s.variable,values=s.value,aggfunc='sum',margins=True)
Out[33]: 
variable      Graduate  Undergraduate   All
index                                      
Not                440           3760  4200
Straight A's        60            240   300
All                500           4000  4500
Run Code Online (Sandbox Code Playgroud)

玩具数据

df=pd.DataFrame({'c1':[1,2,2,3,4],'c2':[2,2,3,3,3],'c3':[1,2,3,4,5]}) 
# before `agg`, I think your input is the result after `groupby` 
df
Out[37]: 
   c1  c2  c3
0   1   2   1
1   2   2   2
2   2   3   3
3   3   3   4
4   4   3   5


pd.crosstab(df.c1,df.c2,df.c3,aggfunc='sum',margins
=True)
Out[38]: 
c2     2     3  All
c1                 
1    1.0   NaN    1
2    2.0   3.0    5
3    NaN   4.0    4
4    NaN   5.0    5
All  3.0  12.0   15
Run Code Online (Sandbox Code Playgroud)