关于pandas groupby中lambda算子的澄清

时间:2018-01-27 19:14:46

标签: pandas lambda

我无法发表评论,因为我不熟悉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分组)。

很抱歉这样一个基本问题,但解释会非常有用!

2 个答案:

答案 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调用后的一组组。