47

dplyrパッケージが簡単にグループ化して複数の要約を実行できるR から pandas への移行に問題があります。

複数の集計のための既存の Python pandas コードの改善にご協力ください:

import pandas as pd
data = pd.DataFrame(
    {'col1':[1,1,1,1,1,2,2,2,2,2],
    'col2':[1,2,3,4,5,6,7,8,9,0],
     'col3':[-1,-2,-3,-4,-5,-6,-7,-8,-9,0]
    }
)
result = []
for k,v in data.groupby('col1'):
    result.append([k, max(v['col2']), min(v['col3'])])
print pd.DataFrame(result, columns=['col1', 'col2_agg', 'col3_agg'])

問題:

  • 冗長すぎる
  • おそらく最適化して効率的にすることができます。for-loop groupby(実装をに書き直したgroupby.aggところ、パフォーマンスが大幅に向上しました)。

R では、同等のコードは次のようになります。

data %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))

更新: @ayhan が私の質問を解決しました。これは、コメントではなくここに投稿するフォローアップの質問です。

Q2)groupby().summarize(newcolumn=max(col2 * col3))関数が 2 つ以上の列の複合関数である集計/要約に相当するものは何ですか?

4

3 に答える 3

83

に相当する

df %>% groupby(col1) %>% summarize(col2_agg=max(col2), col3_agg=min(col3))

df.groupby('col1').agg({'col2': 'max', 'col3': 'min'})

返す

      col2  col3
col1            
1        5    -5
2        9    -9

返されるオブジェクトは pandas.DataFrame であり、インデックスが呼び出されcol1、列がcol2andという名前col3です。デフォルトでは、データ pandas をグループ化すると、効率的なアクセスと変更のために、グループ化列がインデックスとして設定されます。ただし、それを望まない場合はcol1、列として設定する方法が 2 つあります。

  • 合格as_index=False

    df.groupby('col1', as_index=False).agg({'col2': 'max', 'col3': 'min'})
    
  • 電話reset_index

    df.groupby('col1').agg({'col2': 'max', 'col3': 'min'}).reset_index()
    

両方とも

col1  col2  col3           
   1     5    -5
   2     9    -9

複数の関数を に渡すこともできますgroupby.agg

agg_df = df.groupby('col1').agg({'col2': ['max', 'min', 'std'], 
                                 'col3': ['size', 'std', 'mean', 'max']})

これも DataFrame を返しますが、現在は列の MultiIndex を持っています。

     col2               col3                   
      max min       std size       std mean max
col1                                           
1       5   1  1.581139    5  1.581139   -3  -1
2       9   0  3.535534    5  3.535534   -6   0

MultiIndex は、選択とグループ化に非常に便利です。ここではいくつかの例を示します。

agg_df['col2']  # select the second column
      max  min       std
col1                    
1       5    1  1.581139
2       9    0  3.535534

agg_df[('col2', 'max')]  # select the maximum of the second column
Out: 
col1
1    5
2    9
Name: (col2, max), dtype: int64

agg_df.xs('max', axis=1, level=1)  # select the maximum of all columns
Out: 
      col2  col3
col1            
1        5    -1
2        9     0

以前 (バージョン 0.20.0aggより前) は、辞書を使用して呼び出しの列の名前を変更することができました。例えば

df.groupby('col1')['col2'].agg({'max_col2': 'max'})

2 番目の列の最大値を次のように返しますmax_col2

      max_col2
col1          
1            5
2            9

ただし、rename メソッドを支持して廃止されました。

df.groupby('col1')['col2'].agg(['max']).rename(columns={'max': 'col2_max'})

      col2_max
col1          
1            5
2            9

上記で定義したように、DataFrame の詳細を取得できますagg_df。その場合、名前変更関数を使用してこれらのレベルを平坦化できます。

agg_df.columns = ['_'.join(col) for col in agg_df.columns]

      col2_max  col2_min  col2_std  col3_size  col3_std  col3_mean  col3_max
col1                                                                        
1            5         1  1.581139          5  1.581139         -3        -1
2            9         0  3.535534          5  3.535534         -6         0

のような操作ではgroupby().summarize(newcolumn=max(col2 * col3))、最初に で新しい列を追加することで、引き続き agg を使用できますassign

df.assign(new_col=df.eval('col2 * col3')).groupby('col1').agg('max') 

      col2  col3  new_col
col1                     
1        5    -1       -1
2        9     0        0

これは古い列と新しい列の最大値を返しますが、いつものようにそれをスライスできます。

df.assign(new_col=df.eval('col2 * col3')).groupby('col1')['new_col'].agg('max')

col1
1   -1
2    0
Name: new_col, dtype: int64

これgroupby.applyで短くなります:

df.groupby('col1').apply(lambda x: (x.col2 * x.col3).max())

col1
1   -1
2    0
dtype: int64

ただし、groupby.applyこれはカスタム関数として扱われるため、ベクトル化されません。これまで、渡した関数agg('min'、'max'、'min'、'size' など) はベクトル化されており、これらは最適化された関数のエイリアスです。, orに置き換えるdf.groupby('col1').agg('min')と、それらはすべて同じ機能を実行します。カスタム関数を使用すると、同じ効率は得られません。df.groupby('col1').agg(min)df.groupby('col1').agg(np.min)df.groupby('col1').min()

最後に、バージョン 0.20 の時点で、agg最初にグループ化することなく、DataFrame で直接使用できます。ここで例を参照してください。

于 2016-08-13T18:18:21.130 に答える