Python 如何使用百分比制作熊猫交叉表?
给定一个具有不同分类变量的数据帧,如何返回带有百分比而不是频率的交叉列表Python 如何使用百分比制作熊猫交叉表?,python,pandas,crosstab,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.rando
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
使用crosstab中的边距选项来计算行和列的总数使我们足够接近于认为使用aggfunc或groupby应该是可行的,但我贫乏的大脑无法思考到底
B A B C
A
one .33 .33 .33
three .33 .33 .33
two .33 .33 .33
基本上,您只需使用执行row/row.sum()
的函数,然后使用apply
和axis=1
按行应用它
(如果在Python 2中执行此操作,则应使用来自uuu future uuuu import division的,以确保division始终返回浮点。)另一个选项是使用而不是应用:
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'):
如果要查找占总数的百分比,可以除以df的len,而不是行和:
pd.crosstab(df.A, df.B).apply(lambda r: r/len(df), axis=1)
从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
您可以在所有
、索引
(行)或列
之间进行标准化
更多详细信息可用。我们可以用百分比乘以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”
,您需要一个来自未来导入除法的来强制对整数进行浮点除法。没错。我在回答中加了这个。(我的shell设置为自动执行此操作,因此我总是忘记需要执行此操作。)@BrenBarn这里axis=1的重要性是什么。。!?真的不懂@罗希思:不知道你不明白什么。正如我在回答中所说,axis=1按行应用函数。否则,百分比将相对于列总计而不是行总计进行计算。您不希望该表是0.167 0.167 0.167\n 0.083 0.083\n 0.083 0.083 0.083
?我想您特别想要“行内百分比”(例如)。在0.18.1中,看起来您可以传递normalize=“index”此选项的一个好处是,如果包含边际小计,它仍然有效。
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
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