Rからpandasに移行する際に問題があります。ここで、dplyr
パッケージは簡単にグループ化して複数の要約を実行できます。
既存の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+列の複合関数である集約/要約とは何ですか?
と同等
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
返されるオブジェクトは、col1
というインデックスと、col2
およびcol3
という名前の列を持つpandas.DataFrameです。デフォルトでは、データをグループ化するときに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
以前( version 0.20. の前)agg
呼び出しの列の名前を変更するために辞書を使用することが可能でした。例えば
df.groupby('col1')['col2'].agg({'max_col2': 'max'})
2番目の列の最大値をmax_col2
として返します。
max_col2
col1
1 5
2 9
ただし、名前変更メソッドを支持して廃止されました。
df.groupby('col1')['col2'].agg(['max']).rename(columns={'max': 'col2_max'})
col2_max
col1
1 5
2 9
上記で定義したagg_df
のようなDataFrameの場合、冗長になります。その場合、名前変更機能を使用してこれらのレベルをフラット化できます。
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))
などの操作の場合、assign
を使用して新しい列を最初に追加することにより、aggを使用できます。
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'など)はベクトル化され、これらは最適化された関数のエイリアスです。 df.groupby('col1').agg('min')
をdf.groupby('col1').agg(min)
、df.groupby('col1').agg(np.min)
、またはdf.groupby('col1').min()
に置き換えることができ、それらはすべて同じ関数を実行します。カスタム関数を使用する場合、同じ効率は見られません。
最後に、バージョン0.20では、最初にグループ化することなく、agg
をDataFrameで直接使用できます。例を参照してください here 。
Pandas documentation here: http://pandas.pydata.org/pandas-docs/stable/comparison_with_r.html#grouping-and -要約
R's dplyr
gdf <- group_by(df, col1)
summarise(gdf, avg=mean(col1, na.rm=TRUE))
Pandas
gdf = df.groupby('col1')
df.groupby('col1').agg({'col1': 'mean'})