如何在熊猫中创建总和行和总和列?

时间:2018-11-21 15:07:19

标签: python pandas

我正在学习可汗学院的统计课程,这是我上大学时的重温课程,也是一种让我快速学习熊猫和其他科学Python的方法。

我从可汗学院得到了一张看起来像这样的桌子:

             | Undergraduate | Graduate | Total
-------------+---------------+----------+------
Straight A's |           240 |       60 |   300
-------------+---------------+----------+------
Not          |         3,760 |      440 | 4,200
-------------+---------------+----------+------
Total        |         4,000 |      500 | 4,500

我想使用熊猫重新创建此表。当然我可以使用类似的东西创建一个DataFrame

"Graduate": {...},
"Undergraduate": {...},
"Total": {...},

但是,这似乎是一种幼稚的方法,会很快失效,而且实际上并不能扩展。

我的表格的非总计部分如下:

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

我一直在寻找,发现了一些有希望的东西,例如:

df['Total'] = df.sum(axis=1)

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

我确实找到了crosstab函数,它看起来应该可以执行我想要的操作,但是为了做到这一点,我似乎必须为所有这些值创建一个由1/0组成的数据帧,这似乎很愚蠢,因为我已经有了汇总。

我发现一些方法似乎可以手动建立新的总计行,但是似乎应该有更好的方法,例如:

totals(df, rows=True, columns=True)

之类的。

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

4 个答案:

答案 0 :(得分:13)

或者分两步,按照您的建议使用.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 row: 
df.loc['Total',:]= df.sum(axis=0)

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

输出:

              Graduate  Undergraduate  Total
Not                440           3760   4200
Straight A's        60            240    300
Total              500           4000   4500

答案 1 :(得分:8)

appendassign

此答案的重点是提供一个在线解决方案,而不是一个就地解决方案。

append

我使用import { mapState } from 'vuex' computed: mapState({ article: state => state.articles.find(article => article.id == this.$route.params.id) }) 垂直堆叠appendSeries。它还会创建一个DataFrame,以便我可以继续进行链接。

assign

我使用copy添加一列。但是,我正在研究的assign介于两者之间。因此,我在DataFrame参数中使用了lambda,它告诉assign将其应用于调用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 drop来消除潜在的errors='ignore'行和列。

而且,还是在排队。

Total

答案 2 :(得分:4)

根据使用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

玩具数据

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

答案 3 :(得分:0)

原始数据为:

SELECT patid FROM sandbox_jp.claims_women_dx_preg2
UNION
SELECT patid FROM sandbox_jp.claims_women_px_preg2;

您只能使用>>> df = pd.DataFrame(dict(Undergraduate=[240, 3760], Graduate=[60, 440]), index=["Straight A's", "Not"]) >>> df Out: Graduate Undergraduate Straight A's 60 240 Not 440 3760 来重新创建此表:

df.T

按行和列计算>>> df_new = df.T >>> df_new Out: Straight A's Not Graduate 60 440 Undergraduate 240 3760 后:

Total