我无法发表评论,因为我不熟悉stackoverflow,因此无法直接在线程中提问,但我想在此question澄清解决方案:
# From Paul H import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame({'state': ['CA', 'WA', 'CO', 'AZ'] * 3, 'office_id': list(range(1, 7)) * 2, 'sales': [np.random.randint(100000, 999999) for _ in range(12)]}) state_office = df.groupby(['state', 'office_id']).agg({'sales': 'sum'}) # Change: groupby state_office and divide by sum state_pcts = state_office.groupby(level=0).apply(lambda x: 100 * x / float(x.sum()))
我理解多索引选择(0级v。级别1),但我不清楚lambda函数中的每个x
所指的是什么。我x
中的x.sum()
会引用level = 0
(对level = 0
的每个分组中的所有结果求和),x
中的100 * x
似乎是指groupby对象中的每个单独结果(而不是索引level = 0
分组)。
很抱歉这样一个基本问题,但解释会非常有用!
答案 0 :(得分:4)
这是state_office
DataFrame:
state_office
Out:
sales
state office_id
AZ 2 589661
4 339834
6 201054
CA 1 760950
3 935865
5 464993
CO 1 737207
3 154900
5 277555
WA 2 510215
4 640508
6 557411
如果您在level = 0上对此进行分组,则组将为:
sales
state office_id
AZ 2 589661
4 339834
6 201054
sales
state office_id
CA 1 760950
3 935865
5 464993
sales
state office_id
CO 1 737207
3 154900
5 277555
将groupby.apply与自定义函数一起使用时,这些组将成为此函数的输入(lambda x中为x
)。我将使用术语group
而不是x来更明确。
令你困惑的是广播。如果对于特定组,您使用group / group.sum()
,那么它将除以该组中的每个元素。我们来看第一组:
sales
state office_id
AZ 2 589661
4 339834
6 201054
group.sum()
返回:
group.sum()
Out:
sales 1130549
dtype: int64
由于它只有一个元素,float(x.sum())
将返回1130549.0。 (一个更干净的版本将选择GroupBy对象上的销售系列,然后应用该功能。state_office.groupby(level=0)['sales'].apply(lambda x: 100 * x / x.sum())
这里,x
是一个系列,所以x.sum()
将是一个标量,所以你不会需要float(x.sum())
)。
如果您将每个元素除以此值,则会得到所需的结果:
group / group.sum()
Out:
sales
state office_id
AZ 2 0.521570
4 0.300592
6 0.177837
pandas / numpy在这一点上指出,如果形状不同但有一个共同的轴,则应该基于此进行操作(更基本的是,如果传递三个数字而不是元素方式除了你只通过一个数字,它知道你想要用这个单个数字来划分这三个数字中的每一个。)
答案 1 :(得分:1)
让我们一起阅读文档。 (Source)
GroupBy.apply( func ,* args,** kwargs)[source]应用函数func 分组并将结果合并在一起。
从上面的签名中查看func
:
func:function
可以调用将数据帧作为其第一个参数,并返回一个 数据框,一系列或标量。另外,可以调用 位置和关键字参数
在OP的示例中,lambda x: 100 * x / float(x.sum()
在文档中为func
。在文档中,x
这里是一个数据框,是groupby
调用后的一组组。