web-dev-qa-db-ja.com

割合でpandasクロス集計を作成するには?

異なるカテゴリ変数を持つデータフレームがある場合、頻度ではなくパーセンテージでクロス集計を返すにはどうすればよいですか?

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
45
Brian Keegan
_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を返すようにする必要があります。)

49
BrenBarn

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のいずれかで正規化できる場所。

詳細は利用可能です ドキュメントで

56
Harry

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

便宜上、丸めた場所。

3
gabra

合計の割合を探している場合は、行合計ではなく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
2
Andy Hayden