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

给定一个具有不同分类变量的数据框架,如何用百分比而不是频率返回交叉表格?

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
94850 次浏览
pd.crosstab(df.A, df.B).apply(lambda r: r/r.sum(), axis=1)

基本上,您只有执行 row/row.sum()的函数,并且使用 applyaxis=1逐行应用它。

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

另一种选择是使用 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

如果你要找总数的一个百分比,你可以除以 df 的 len 而不是行和:

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

从熊猫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进行标准化。

更多细节可参考 在文件中

我们可以用百分比乘以 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

为了方便,我绕了一圈。

标准化索引只是简单的工作。使用参数,pd.crosstab()中的 normalize = "index"