熊猫如何将函数应用于 groupby().first()

Posted

技术标签:

【中文标题】熊猫如何将函数应用于 groupby().first()【英文标题】:Pandas how to apply a function to groupby().first() 【发布时间】:2021-11-20 20:29:43 【问题描述】:

我有一个df,代码是:

  df = """
      ValOption  RB test contrat
    0       SLA  4  3    23
    1       AC   5  4    12
    2       SLA  5  5    23
    3       AC   2  4    39
    4       SLA  5  5    26
    5       AC   3  4    52
    6       SLA  4  3    64
    0       SLA  4  3    23
    1       AC   5  4    12
    2       SLA  5  5    23
    3       AC   2  4    39
    4       SLA  5  5    26
    5       AC   5  4    52
    6       SLA  4  3    64
  
    """
df = pd.read_csv(StringIO(df.strip()), sep='\s+')

输出:

       ValOption  RB  test  contrat

    0       SLA   4     3       23
    1        AC   5     4       12
    2       SLA   5     5       23
    3        AC   2     4       39
    4       SLA   5     5       26
    5        AC   3     4       52
    6       SLA   4     3       64
    0       SLA   4     3       23
    1        AC   5     4       12
    2       SLA   5     5       23
    3        AC   2     4       39
    4       SLA   5     5       26
    5        AC   5     4       52
    6       SLA   4     3       64

现在我将它分组并获得第一个:

df_u=df.groupby(['RB','test']).first()

输出:

然后我想对每一行应用一个函数,由于某种原因我必须使用 pd.apply() 函数:

def func(row):
    v1=row['RB']*3
    v2=row['test']-1
    return v1+v2

df_u['new_col']=df_u.apply(lambda row:func(row), axis=1)

注意:在实际业务中该函数非常复杂且冗长,所以我需要使用pd.apply()

然后我得到一个错误:

KeyError: ('RB', 'occurred at index (2, 4)')

【问题讨论】:

【参考方案1】:

您必须reset_index 才能访问“RB”和“test”行。使用.values 将值设置为new_col

df_u['new_col'] = df_u.reset_index().apply(func, axis=1).values
print(df_u)

# Output:
        ValOption  contrat  new_col
RB test                            
2  4           AC       39        9
3  4           AC       52       12
4  3          SLA       23       14
5  4           AC       12       18
   5          SLA       23       19

更新

如何将new_col返回到原来的df?

df = df.merge(df.drop_duplicates(['RB', 'test'])
                .assign(new_col=func)[['RB', 'test', 'new_col']],
              on=['RB', 'test'], how='left')

# Output
   ValOption  RB  test  contrat  new_col
0        SLA   4     3       23       14
1         AC   5     4       12       18
2        SLA   5     5       23       19
3         AC   2     4       39        9
4        SLA   5     5       26       19
5         AC   3     4       52       12
6        SLA   4     3       64       14
7        SLA   4     3       23       14
8         AC   5     4       12       18
9        SLA   5     5       23       19
10        AC   2     4       39        9
11       SLA   5     5       26       19
12        AC   5     4       52       18
13       SLA   4     3       64       14

更新2

我 drop_duplicates 的原因是为了节省时间,让它更快 因为行的长度是60k,如果我应用到每一行,它会花费很多时间,而不是如果我先删除重复的,我不需要应用到每一行,我直接将值分配给相同的列值行

Apply 是类似 for 循环的,使用向量化:

df['new_col'] = (df['RB']*3) + (df['test']-1)

性能

对于 140,000 条记录,上述操作耗时 361 µs:

%timeit (df1['RB']*3) + (df1['test']-1)
361 µs ± 9.02 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

对于 14 条记录(不是错误),之前的操作耗时 935 µs:

%timeit df.drop_duplicates(['RB', 'test']).apply(func, axis=1)
935 µs ± 5.44 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

非常感谢,还有一个问题,如何将new_col返回到原始df? 您想只为每个第一个实例或所有行设置值吗? 我更新了我的答案。让我知道这是否符合您的预期? 再次感谢您,但不是 NaN,而是如何将真正的 new_col 值放在重复的行中。我 drop_duplicates 的原因是为了节省时间,让它更快,但在最后每一行应该有一个 new_col 值。 您确定节省时间吗?过滤、应用和恢复可能比在整个数据帧上应用要慢。

以上是关于熊猫如何将函数应用于 groupby().first()的主要内容,如果未能解决你的问题,请参考以下文章

熊猫有效地将groupby函数应用于每一列[重复]

如何正确使用带有应用功能的熊猫 groupby 来解决副作用? (第一组申请两次)

熊猫数据框:groupby 和 plot 有两个不同的列

如何调试熊猫 groupby 应用功能

熊猫 groupby 和 qcut

如何将自定义函数应用于每行的熊猫数据框[重复]