web-dev-qa-db-ja.com

Python Pandas groupby apply lambda arguments

Python Pandas groupby(Pythonコースの紹介))のコースラビデオでは、次の例は与えられた:

df.groupby('Category').apply(lambda df,a,b: sum(df[a] * df[b]), 'Weight (oz.)', 'Quantity')

ここで、dfはDataFrameであり、ラムダは2つの列の合計を計算するために適用されます。私が正しく理解している場合、適用関数が呼び出されるgroupbyオブジェクト(groupbyによって返される)は、グループ化されたインデックスと、その特定のグループ化であるDataFrameの一部で構成される一連のタプルです。

私が理解していないのはラムダの使い方です:

3つの引数が指定されています(lambda df、a、b)が、明示的に渡されるのは2つだけです( 'Weight(oz。)'および 'Quantity')。インタプリタは、引数「a」と「b」が引数として指定されたものであり、dfが「そのまま」使用されていることをどのようにして知るのですか?

私はドキュメントを調べましたが、そのような特定の例の決定的な答えは見つかりませんでした。これはdfのスコープ内で何かを行う必要があると思いますが、サポートする情報やその考えの詳細を見つけることができません。

8
g_uint

Applyメソッド自体は、関数の最初の引数としてgroupbyオブジェクトの各「グループ」を渡します。そのため、位置に基づいて「重量」と「数量」をabに関連付けることがわかっています。 (たとえば、最初の「グループ」引数を数える場合、これらは2番目と3番目の引数です。

df = pd.DataFrame(np.random.randint(0,11,(10,3)), columns = ['num1','num2','num3'])
df['category'] = ['a','a','a','b','b','b','b','c','c','c']
df = df[['category','num1','num2','num3']]
df

  category  num1  num2  num3
0        a     2     5     2
1        a     5     5     2
2        a     7     3     4
3        b    10     9     1
4        b     4     7     6
5        b     0     5     2
6        b     7     7     5
7        c     2     2     1
8        c     4     3     2
9        c     1     4     6

gb = df.groupby('category')

暗黙の引数はそれぞれ「グループ」、またはこの場合は各カテゴリです

gb.apply(lambda grp: grp.sum()) 

"grp"はラムダ関数の最初の引数であり、これまでのように何も指定する必要はありません。自動的にgroupbyオブジェクトの各グループと見なされます。

         category  num1  num2  num3
category                           
a             aaa    14    13     8
b            bbbb    21    28    14
c             ccc     7     9     9

したがって、applyはこれらのそれぞれを通過し、合計操作を実行します

print(gb.groups)
{'a': Int64Index([0, 1, 2], dtype='int64'), 'b': Int64Index([3, 4, 5, 6], dtype='int64'), 'c': Int64Index([7, 8, 9], dtype='int64')}

print('1st GROUP:\n', df.loc[gb.groups['a']])
1st GROUP:
  category  num1  num2  num3
0        a     2     5     2
1        a     5     5     2
2        a     7     3     4    


print('SUM of 1st group:\n', df.loc[gb.groups['a']].sum())

SUM of 1st group:
category    aaa
num1         14
num2         13
num3          8
dtype: object

これが前の操作の最初の行と同じであることに注意してください

したがって、applyはimplicitly各グループを最初の引数として関数の引数に渡します。

docs から

GroupBy.apply(func、* args、** kwargs)

args、kwargs:タプルとディクテーション

Funcに渡すオプションの位置引数とキーワード引数

"* args"で渡された追加の引数は、暗黙のグループ引数の後に後に渡されます

あなたのコードを使用して

gb.apply(lambda df,a,b: sum(df[a] * df[b]), 'num1', 'num2')

category
a     56
b    167
c     20
dtype: int64

ここで 'num1'および 'num2'は、ラムダ関数の各呼び出しにadditional引数として渡されています

したがって、applyはこれらのそれぞれを通過し、ラムダ演算を実行します

# copy and paste your lambda function
fun = lambda df,a,b: sum(df[a] * df[b])

print(gb.groups)
{'a': Int64Index([0, 1, 2], dtype='int64'), 'b': Int64Index([3, 4, 5, 6], dtype='int64'), 'c': Int64Index([7, 8, 9], dtype='int64')}

print('1st GROUP:\n', df.loc[gb.groups['a']])

1st GROUP:
   category  num1  num2  num3
0        a     2     5     2
1        a     5     5     2
2        a     7     3     4

print('Output of 1st group for function "fun":\n', 
fun(df.loc[gb.groups['a']], 'num1','num2'))

Output of 1st group for function "fun":
56
8
RSHAP