如何用百分比制作熊猫交叉表?

时间:2014-01-21 00:57:56

标签: python pandas crosstab

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

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

6 个答案:

答案 0 :(得分:53)

从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

答案 1 :(得分:47)

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确保除法始终返回浮点数。)

答案 2 :(得分:3)

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

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

答案 3 :(得分:3)

我们可以乘以$('#GridId').data('kendoGrid').dataSource.read().then(function() { $('#GridId').data('kendoGrid').refresh(); });

将其显示为百分比
100

我为了方便起见。

答案 4 :(得分: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

答案 5 :(得分:1)

对索引进行归一化即可解决。在normalize = "index"中使用参数pd.crosstab()