【问题标题】:How do I create a sum row and sum column in pandas?如何在 pandas 中创建求和行和求和列?
【发布时间】:2019-09-05 22:53:57
【问题描述】:

我正在学习可汗学院的统计学课程,作为我大学时代的复习,并作为一种让我快速了解熊猫和其他科学 Python 的方法。

我有一张来自可汗学院的桌子,看起来像这样:

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

我想使用 pandas 重新创建此表。当然,我可以使用类似的东西创建一个 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)

什么的。

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

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    或者分两步,按照您的建议使用.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)
    

    输出:

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

    【讨论】:

    • 嗯...虽然这给了我一些奇怪的输出 - 3760+440 不是 8400,但这就是它所显示的内容??
    • 这很奇怪,我应该得到 4200?也许是错字?
    • @WayneWerner 那是因为这是一个就地操作。看来你已经运行了两次
    • 啊,我一定是不小心在我的笔记本上按了 ctrl+enter。这次我做了一个副本来操作:)
    【解决方案2】:

    appendassign

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

    append

    我使用append 垂直堆叠SeriesDataFrame。它还创建了一个copy,以便我可以继续链接。

    assign

    我使用assign 添加一列。然而,我正在研究的DataFrame 位于虚空之间。所以我在assign 参数中使用了lambda,它告诉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
    

    有趣的选择

    droperrors='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
    

    【讨论】:

      【解决方案3】:

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

      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
      

      【讨论】:

        【解决方案4】:

        原始数据为:

        >>> 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后:

        >>> df_new.loc['Total',:]= df_new.sum(axis=0)
        >>> df_new.loc[:,'Total'] = df_new.sum(axis=1)
        >>> df_new
        Out: 
                       Straight A's     Not   Total
        Graduate               60.0   440.0   500.0
        Undergraduate         240.0  3760.0  4000.0
        Total                 300.0  4200.0  4500.0
        

        【讨论】:

          猜你喜欢
          • 2014-10-21
          • 2020-12-06
          • 2015-09-09
          • 2019-01-25
          • 1970-01-01
          • 2019-01-28
          • 1970-01-01
          • 2020-08-03
          • 2020-12-20
          相关资源
          最近更新 更多