鉴于数据框具有不同的分类变量,如何返回包含百分比而不是频率的交叉表?
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 :(得分: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
您可以在all
,index
(行)或columns
之间进行标准化。
有更多详情可供in the documentation。
答案 1 :(得分:47)
pd.crosstab(df.A, df.B).apply(lambda r: r/r.sum(), axis=1)
基本上你只有row/row.sum()
的功能,并且apply
和axis=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()
。