澄清熊猫 groupby 中的 lambda 运算符

jba*_*rdo 3 python lambda pandas

我无法发表评论,因为我是 stackoverflow 的新手,所以不能直接在线程中提问,但我想澄清这个问题中的解决方案:

# 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()))
Run Code Online (Sandbox Code Playgroud)

我了解多索引选择(级别 0 与级别 1),但我不清楚xlambda 函数中的每个索引是指什么。将xx.sum()会向我提及level = 0(总结中的每个分组在所有的结果level = 0),但x100 * x似乎是指每个单独的结果GROUPBY对象(而不是在索引中level = 0分组)。

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

ayh*_*han 5

这是数据state_office框:

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
Run Code Online (Sandbox Code Playgroud)

如果您在 level=0 上对其进行分组,则这些组将是:

                  sales
state office_id        
AZ    2          589661
      4          339834
      6          201054
Run Code Online (Sandbox Code Playgroud)
                  sales
state office_id        
CA    1          760950
      3          935865
      5          464993
Run Code Online (Sandbox Code Playgroud)
                  sales
state office_id        
CO    1          737207
      3          154900
      5          277555
Run Code Online (Sandbox Code Playgroud)

当您将 groupby.apply 与自定义函数一起使用时,这些组将成为此函数的输入(x在 lambda x 中)。group为了更明确,我将使用该术语而不是 x。

让你困惑的东西叫做广播。如果对于您使用的特定组,group / group.sum()那么它将将该组中的每个元素除以总和。我们先来看第一组:

                  sales
state office_id        
AZ    2          589661
      4          339834
      6          201054
Run Code Online (Sandbox Code Playgroud)

group.sum() 返回:

group.sum()
Out: 
sales    1130549
dtype: int64
Run Code Online (Sandbox Code Playgroud)

由于它只有一个元素,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
Run Code Online (Sandbox Code Playgroud)

pandas/numpy 在这一点上指出,如果形状不相同但有一个共同的轴,则应基于此进行操作(更基本的是,如果您传递三个数字,则它会进行元素划分,但由于您只传递一个数字,它知道您想将这三个数字中的每一个除以这个数字)。