【问题标题】:How to make a pandas crosstab with percentages?如何用百分比制作熊猫交叉表?
【发布时间】:2014-02-10 09:39:03
【问题描述】:

给定具有不同分类变量的数据框,我如何返回包含百分比而不是频率的交叉表?

df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 6,
                   'B' : ['A', 'B', 'C'] * 8,
                   'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 4,
                   'D' : np.random.randn(24),
                   'E' : np.random.randn(24)})


pd.crosstab(df.A,df.B)


B       A    B    C
A               
one     4    4    4
three   2    2    2
two     2    2    2

使用交叉表中的边距选项来计算行和列总计让我们足够接近认为应该可以使用 aggfunc 或 groupby,但我微薄的大脑无法思考。

B       A     B    C
A               
one     .33  .33  .33
three   .33  .33  .33
two     .33  .33  .33

【问题讨论】:

  • 你不希望表格是0.167 0.167 0.167\n 0.083 0.083 0.083\n 0.083 0.083 0.083吗?
  • 我想你特别想要“行内百分比”(例如en.wikipedia.org/wiki/Crosstab)。
  • 在 Pandas 0.18.1 中,您似乎可以通过 normalize="index" 将每个条目划分为行的 sum 。

标签: python pandas crosstab


【解决方案1】:
pd.crosstab(df.A, df.B).apply(lambda r: r/r.sum(), axis=1)

基本上你只有 row/row.sum() 的函数,你可以使用 applyaxis=1 来逐行应用它。

(如果在 Python 2 中执行此操作,则应使用 from __future__ import division 以确保除法始终返回浮点数。)

【讨论】:

  • 你需要一个from __future__ import division 来强制对整数进行浮点除法。
  • 确实如此。我将其添加到我的答案中。 (我的 shell 设置为自动执行此操作,所以我总是忘记它需要完成。)
  • @BrenBarn 这里axis=1的重要性是什么......!?实在看不懂..!
  • @Rohith:不知道你不明白什么。正如我在回答中所说,axis=1 by row 应用函数。否则,百分比将相对于列总计而不是行总计来计算。
【解决方案2】:

另一种选择是使用div 而不是应用:

In [11]: res = pd.crosstab(df.A, df.B)

除以总和:

In [12]: res.sum(axis=1)
Out[12]: 
A
one      12
three     6
two       6
dtype: int64

与上面类似,你需要对整数除法做一些事情(我使用 astype('float')):

In [13]: res.astype('float').div(res.sum(axis=1), axis=0)
Out[13]: 
B             A         B         C
A                                  
one    0.333333  0.333333  0.333333
three  0.333333  0.333333  0.333333
two    0.333333  0.333333  0.333333

【讨论】:

    【解决方案3】:

    如果您正在寻找总数的百分比,您可以除以 df 的 len 而不是行总和:

    pd.crosstab(df.A, df.B).apply(lambda r: r/len(df), axis=1)
    

    【讨论】:

      【解决方案4】:

      从 Pandas 0.18.1 开始,有一个 normalize 选项:

      In [1]: pd.crosstab(df.A,df.B, normalize='index')
      Out[1]:
      
      B              A           B           C
      A           
      one     0.333333    0.333333    0.333333
      three   0.333333    0.333333    0.333333
      two     0.333333    0.333333    0.333333
      

      您可以在 allindex(行)或 columns 之间进行标准化。

      更多详情请见in the documentation

      【讨论】:

      • 此选项的一个好处是,如果您包括边际小计,它仍然有效。
      【解决方案5】:

      我们可以通过乘以100 将其显示为百分比:

      pd.crosstab(df.A,df.B, normalize='index')\
          .round(4)*100
      
      B          A      B      C
      A                         
      one    33.33  33.33  33.33
      three  33.33  33.33  33.33
      two    33.33  33.33  33.33
      

      为方便起见,我已四舍五入。

      【讨论】:

        【解决方案6】:

        标准化索引将很容易解决。在pd.crosstab()中使用参数normalize = "index"

        【讨论】:

          猜你喜欢
          • 2017-03-11
          • 1970-01-01
          • 2022-11-17
          • 2023-01-26
          • 2022-01-21
          • 1970-01-01
          • 2021-09-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多