異なるカテゴリ変数を持つデータフレームがある場合、頻度ではなくパーセンテージでクロス集計を返すにはどうすればよいですか?
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
_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
_を使用して、除算が常にfloatを返すようにする必要があります。)
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
のいずれかで正規化できる場所。
詳細は利用可能です ドキュメントで 。
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
便宜上、丸めた場所。
合計の割合を探している場合は、行合計ではなくdfのlenで除算できます。
pd.crosstab(df.A, df.B).apply(lambda r: r/len(df), axis=1)
別のオプションは、適用するのではなく 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