14

私の問題は、 pandas で複数の変数の頻度を計算する方法です。私はこのデータフレームから持っています:

d1 = pd.DataFrame( {'StudentID': ["x1", "x10", "x2","x3", "x4", "x5", "x6",   "x7",     "x8", "x9"],
                       'StudentGender' : ['F', 'M', 'F', 'M', 'F', 'M', 'F', 'M', 'M', 'M'],
                 'ExamenYear': ['2007','2007','2007','2008','2008','2008','2008','2009','2009','2009'],
                 'Exam': ['algebra', 'stats', 'bio', 'algebra', 'algebra', 'stats', 'stats', 'algebra', 'bio', 'bio'],
                 'Participated': ['no','yes','yes','yes','no','yes','yes','yes','yes','yes'],
                  'Passed': ['no','yes','yes','yes','no','yes','yes','yes','no','yes']},
                  columns = ['StudentID', 'StudentGender', 'ExamenYear', 'Exam', 'Participated', 'Passed'])

次の結果へ

             Participated  OfWhichpassed
 ExamenYear                             
2007                   3              2
2008                   4              3
2009                   3              2

(1) 私が試した 1 つの可能性は、2 つのデータフレームを計算してそれらをバインドすることです

t1 = d1.pivot_table(values = 'StudentID', rows=['ExamenYear'], cols = ['Participated'], aggfunc = len)
t2 = d1.pivot_table(values = 'StudentID', rows=['ExamenYear'], cols = ['Passed'], aggfunc = len)
tx = pd.concat([t1, t2] , axis = 1)

Res1 = tx['yes']

(2) 2 番目の可能性は、集計関数を使用することです。

import collections
dg = d1.groupby('ExamenYear')
Res2 = dg.agg({'Participated': len,'Passed': lambda x : collections.Counter(x == 'yes')[True]})

 Res2.columns = ['Participated', 'OfWhichpassed']

どちらの方法も、控えめに言っても厄介です。 これはパンダでどのように適切に行われますか?

PS: collections.Counter の代わりに value_counts も試しまし、動作しませんでした

参考までに: 数か月前に、ここで R に同様の質問をし たところ、plyrが役に立ちました。

- - アップデート - - -

ユーザーDSMは正しいです。目的のテーブル結果に誤りがありました。

(1) オプション 1 のコードは次のとおりです。

 t1 = d1.pivot_table(values = 'StudentID', rows=['ExamenYear'], aggfunc = len)
 t2 = d1.pivot_table(values = 'StudentID', rows=['ExamenYear'], cols = ['Participated'], aggfunc = len)
 t3 = d1.pivot_table(values = 'StudentID', rows=['ExamenYear'], cols = ['Passed'], aggfunc = len)

 Res1 = pd.DataFrame( {'All': t1,
                       'OfWhichParticipated': t2['yes'],
                     'OfWhichPassed': t3['yes']})

それは結果を生み出すでしょう

             All  OfWhichParticipated  OfWhichPassed
ExamenYear                                         
2007          3                    2              2
2008          4                    3              3
2009          3                    3              2

(2) オプション 2 については、ユーザーherrfzのおかげで、value_count の使用方法がわかりました。コードは次のようになります。

Res2 = d1.groupby('ExamenYear').agg({'StudentID': len,
                                 'Participated': lambda x: x.value_counts()['yes'],
                                 'Passed': lambda x: x.value_counts()['yes']})

Res2.columns = ['All', 'OfWgichParticipated', 'OfWhichPassed']

Res1 と同じ結果が生成されます

私の質問は残っています:

オプション 2 を使用すると、同じ変数を (別の操作で) 2 回使用できますか? 結果の変数にカスタム名を渡すことはできますか?

---- 新しいアップデート ----

私は最終的に、より柔軟であると理解しているapplyを使用することにしました。

4

4 に答える 4

12

最終的にapplyを使用することにしました。

他の人に役立つことを願って、私が思いついたものを投稿しています。

ウェスの本「Python for Data analysis」からわかることから

  • 独自の関数を定義できるため、applyは agg や transform よりも柔軟です。
  • 唯一の要件は、関数がpandas オブジェクトまたはスカラー値を返すことです。
  • 内部メカニズム: グループ化されたオブジェクトの各部分で関数が呼び出され、結果はpandas.concatを使用して結合されます。
  • 最後に必要な構造を「ハードコード」する必要があります

これが私が思いついたものです

def ZahlOccurence_0(x):
      return pd.Series({'All': len(x['StudentID']),
                       'Part': sum(x['Participated'] == 'yes'),
                       'Pass' :  sum(x['Passed'] == 'yes')})

私がそれを実行すると:

 d1.groupby('ExamenYear').apply(ZahlOccurence_0)

正しい結果が得られます

            All  Part  Pass
ExamenYear                 
2007          3     2     2
2008          4     3     3
2009          3     3     2

このアプローチにより、頻度を他の統計と組み合わせることもできます

import numpy as np
d1['testValue'] = np.random.randn(len(d1))

def ZahlOccurence_1(x):
    return pd.Series({'All': len(x['StudentID']),
        'Part': sum(x['Participated'] == 'yes'),
        'Pass' :  sum(x['Passed'] == 'yes'),
        'test' : x['testValue'].mean()})


d1.groupby('ExamenYear').apply(ZahlOccurence_1)


            All  Part  Pass      test
ExamenYear                           
2007          3     2     2  0.358702
2008          4     3     3  1.004504
2009          3     3     2  0.521511

他の誰かがこれが役立つことを願っています

于 2013-03-25T09:38:12.973 に答える
9

デフォルトで 2 つ以上の変数の度数分布表を計算するpandas crosstab関数を使用できます。例えば、

> import pandas as pd
> pd.crosstab(d1['ExamenYear'], d1['Passed'])
Passed      no  yes
ExamenYear         
2007         1    2
2008         1    3
2009         1    2

margins=True各行と列の小計も表示する場合は、このオプションを使用します。

> pd.crosstab(d1['ExamenYear'], d1['Participated'], margins=True)
Participated  no  yes  All
ExamenYear                
2007           1    2    3
2008           1    3    4
2009           0    3    3
All            2    8   10
于 2016-08-19T05:59:41.527 に答える
8

これ:

d1.groupby('ExamenYear').agg({'Participated': len, 
                              'Passed': lambda x: sum(x == 'yes')})

Rソリューションよりも厄介に見えません.IMHO.

于 2013-03-23T17:41:51.737 に答える