python - 如何优化groupby上的apply调用

标签 python python-3.x pandas apply

我有一个数据框,我想在其上应用以下逻辑来获取对各个组进行分析的组的第一行。

def mark_wakeup_source(df):
    min_id = df['Astart'].idxmin()
    df.loc[min_id, ["Reason", "Count", "CSwitch", "Used"]] = [df.loc[min_id, "type"],
                                                             len(df.index),
                                                             len(df[df['type'] == "Process"]),
                                                             df["Aduration"].sum()]
    return df

以下是我调用 apply 函数并将其组合的方式。

df_t1 = df_t[df_t['type'] != 'Unknown'].copy()
df_t1['Reason'] = "None"
grouped = df_t1.groupby(["CPU", "index"])
df_t1 = grouped.apply(mark_wakeup_source)
df_t = df_t1.append(df_t[df_t['type'] == 'Unknown'])

我当前的数据中有 29K+ 个独特的组,处理大约需要 140 秒。我的数据比这个大得多,我需要优化它,但不知道如何去做。

在分组之前,我的数据如下所示:

    CPU   State     Start      Stop pre_state next_state  index    Astart  \
0     4  Active  0.015417  0.056283        C1         C1      1  0.015429
1     4  Active  0.015417  0.056283        C1         C1      1  0.015437
18    5  Active  0.015492  0.015499        C1         C1      2  0.015495
14    4  Active  0.015417  0.056283        C1         C1      1  0.019524
20    1  Active  0.019921  0.020071        C3         C3      1  0.019938

   Astop          Name     type  Count  CSwitch  Used  Reason  Aduration
0   0.015437        System  Process      0        0     0     None   0.000008
1   0.032188       wpr.exe  Process      0        0     0     None   0.016751
18  0.015498        System  Process      0        0     0     None   0.000003
14  0.019727  ntoskrnl.exe      DPC      0        0     0     None   0.000203
20  0.020064        System  Process      0        0     0     None   0.000126

我已经尽可能减少了组的数量。 尝试过 Numba 但根本没有帮助。 基于许多其他答案,我尝试了下面的代码,通过返回 0 而不是 df,这需要大约 180 秒:

def mark_wakeup_source(df, df_parent):
    df_len = len(df.index)
    min_id = df['Astart'].idxmin()
    df_parent.loc[min_id, ["Reason", "Count", "CSwitch", "Used"]] = 
                                                                 [df.loc[min_id, "type"],
                                                                 df_len,
                                                                 len(df[df['type'] == "Process"]),
                                                                 df["Aduration"].sum()]
    return 0

没有线索,因此寻找一些建议以最佳方式做到这一点。

最佳答案

从聚合函数的字典开始。

f = {
       'Astart' : [('Reason', 'idxmin')], 
       'type' : [
                  ('Count', 'size'), 
                  ('CSwitch', lambda x: x.eq('Process').sum())
        ], 
       'Aduration' : [('Used', 'sum')]
}

接下来,query + groupby 并将 f 传递给 agg

v = df.query("type != 'Unknown'").groupby(['CPU', 'index']).agg(f)
v.columns = v.columns.droplevel(0)

v['Reason'] = df.loc[v['Reason'].values, 'type'].values

v

           Reason  Count  CSwitch      Used
CPU index                                  
1   1          20      1        1  0.000126
4   1           0      3        2  0.016962
5   2          18      1        1  0.000003

请注意,这里使用 agg 聚合数据要快很多,因为它矢量化您的操作(这比循环更快)就像应用解决方案)。

关于python - 如何优化groupby上的apply调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48273294/

相关文章:

python - 如果值位于另一个数据帧中,如何从一个数据帧获取行

Python 设置小数位范围而不四舍五入?

python - Django Rest Framework - 使用与 __all__ 的反向关系

Python cx_Oracle 绑定(bind)变量

python - cv2 模块的 cap.get(7) 函数返回的总帧数不正确

python - 检索当前行和上一个/下一个正值之间的行数

python - Django - 日志配置

python - 对矩阵中的第一列和第二个列表执行 "AND"操作

python - 如何将 Django 的设置对象变成字典?

python - 映射多个数据框的值并填充列