Python Pandas groupby apply lambda arguments
在有关Python Pandas groupby的课程视频中(在Python数据科学入门课程中)给出了以下示例:
1 | df.groupby('Category').apply(lambda df,a,b: sum(df[a] * df[b]), 'Weight (oz.)', 'Quantity') |
其中df是一个DataFrame,并且应用lambda来计算两列的总和。
如果我理解正确,则调用apply函数的groupby对象(由groupby返回)是一系列元组,由组成分组的索引和作为特定分组的DataFrame部分组成。
我不了解lambda的使用方式:
指定了三个参数(lambda df,a,b),但仅显式传递了两个参数(" Weight(oz。)"和" Quantity")。解释器如何知道参数'a'和'b'是指定为参数的参数,而df是按原样使用的?
我看了看文档,但找不到这样一个具体示例的明确答案。我认为这与df的作用有关,但是无法找到支持和详细说明该思想的信息。
apply方法本身将groupby对象的每个"组"作为函数的第一个参数传递。因此,它知道根据位置将"权重"和"数量"关联到
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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') |
隐式参数是每个"组",在这种情况下是每个类别
1 | gb.apply(lambda grp: grp.sum()) |
" grp"是lambda函数的第一个参数
注意,我不必为其指定任何内容,它会自动作为groupby对象的每个组
1 2 3 4 5 | category num1 num2 num3 category a aaa 14 13 8 b bbbb 21 28 14 c ccc 7 9 9 |
因此,应用遍历所有这些并执行求和运算
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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: ', 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: ', df.loc[gb.groups['a']].sum()) SUM of 1st group: category aaa num1 14 num2 13 num3 8 dtype: object |
注意,这与我们先前操作的第一行相同
因此apply是将每个组作为第一个参数隐式传递给函数参数。
来自文档
GroupBy.apply(func, *args, **kwargs)
args, kwargs : tuple and dict
Optional positional and keyword arguments to pass to func
blockquote>
在" * args"中传递的其他Args在隐式组参数之后传递。
所以用你的代码
1
2
3
4
5
6
7 gb.apply(lambda df,a,b: sum(df[a] * df[b]), 'num1', 'num2')
category
a 56
b 167
c 20
dtype: int64此处," num1"和" num2"作为附加参数传递给lambda函数的每次调用
因此,应用遍历所有这些并执行lambda操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 # 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:
', 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":
',
fun(df.loc[gb.groups['a']], 'num1','num2'))
Output of 1st group for function"fun":
56