web-dev-qa-db-ja.com

Pandas GroupBy.applyメソッドは最初のグループを複製します

私の最初のSO質問:pandas(0.12.0-4)のgroupbyのapplyメソッドのこの動作について混乱しています、関数を適用しているようですTWICEをデータフレームの最初の行に追加します。次に例を示します。

>>> from pandas import Series, DataFrame
>>> import pandas as pd
>>> df = pd.DataFrame({'class': ['A', 'B', 'C'], 'count':[1,0,2]})
>>> print(df)
   class  count  
0     A      1  
1     B      0    
2     C      2

最初にgroupby関数が正常に動作することを確認しましたが、問題ないようです。

>>> for group in df.groupby('class', group_keys = True):
>>>     print(group)
('A',   class  count
0     A      1)
('B',   class  count
1     B      0)
('C',   class  count
2     C      2)

次に、groupbyオブジェクトでapplyを使用して同様のことを試み、最初の行の出力を2回取得します。

>>> def checkit(group):
>>>     print(group)
>>> df.groupby('class', group_keys = True).apply(checkit)
  class  count
0     A      1
  class  count
0     A      1
  class  count
1     B      0
  class  count
2     C      2

何か助けていただければ幸いです!ありがとう。

編集:@ジェフは以下の答えを提供します。私は密で、すぐには理解できなかったので、上の例の最初のグループの二重印刷にかかわらず、applyメソッドは最初のグループで1回だけ動作し、元のデータフレームを変更しないことを示す簡単な例を次に示します:

>>> def addone(group):
>>>     group['count'] += 1
>>>     return group

>>> df.groupby('class', group_keys = True).apply(addone)
>>> print(df)

      class  count
0     A      1
1     B      0
2     C      2

しかし、メソッドの戻り値を新しいオブジェクトに割り当てると、期待どおりに機能することがわかります。

df2 = df.groupby( 'class'、group_keys = True).apply(addone)print(df2)

      class  count
0     A      2
1     B      1
2     C      3
38

説明されている here および here のように、これは設計によるものです。

apply関数は、返されるデータの形状を認識して、どのように結合されるかをインテリジェントに把握する必要があります。これを行うには、関数(あなたの場合はcheckit)を2回呼び出してこれを実現します。

実際の使用例に応じて、applyへの呼び出しをaggregatetransformまたはfilterに置き換えることができます。詳細は こちら 。これらの関数は、戻り値が特定の形状である必要があるため、関数を2回呼び出さないでください。

ただし、呼び出す関数に副作用がない場合は、最初の値で関数が2回呼び出されていることは問題ではありません。

37
Zero

この「問題」は修正されました:0.25以上にアップグレードしてください

V0.25以降、GroupBy.apply()は最初のグループを1回だけ評価します。 GH24748 を参照してください。

ドキュメントからの関連する例:

pd.__version__                                                                                                          
# '0.25.0.dev0+590.g44d5498d8'

df = pd.DataFrame({"a": ["x", "y"], "b": [1, 2]})                                                                      

def func(group): 
    print(group.name) 
    return group                                                                                                                     

新しい動作(> = v0.25):

df.groupby('a').apply(func)                                                                                            
x
y

   a  b
0  x  1
1  y  2

以前の動作(<= v0.24.x):

df.groupby('a').apply(func)
x
x
y

   a  b
0  x  1
1  y  2

パンダはまだ最初のグループを使用して、applyが高速パスを使用できるかどうかを判断します。しかし、少なくとも最初のグループを2回評価する必要はありません。よくできました、開発者!

9
cs95

forループを使用して、groupby.applyの最初の行の重複を回避できます。

log_sample.csv

guestid,keyword
1,null
2,null
2,null
3,null
3,null
3,null
4,null
4,null
4,null
4,null

私のコードの抜粋

df=pd.read_csv("log_sample.csv") 
grouped = df.groupby("guestid")

for guestid, df_group in grouped:
    print(list(df_group['guestid'])) 

df.head(100)

出力

[1]
[2, 2]
[3, 3, 3]
[4, 4, 4, 4]
2
geosmart