Pandas:具有多种功能的分组和聚合

Xuk*_*rao 5 python aggregate dataframe pandas

情况

我有一个 pandas 数据框定义如下:

import pandas as pd

headers = ['Group', 'Element', 'Case', 'Score', 'Evaluation']
data = [
    ['A', 1, 'x', 1.40, 0.59],
    ['A', 1, 'y', 9.19, 0.52],
    ['A', 2, 'x', 8.82, 0.80],
    ['A', 2, 'y', 7.18, 0.41],
    ['B', 1, 'x', 1.38, 0.22],
    ['B', 1, 'y', 7.14, 0.10],
    ['B', 2, 'x', 9.12, 0.28],
    ['B', 2, 'y', 4.11, 0.97],
]
df = pd.DataFrame(data, columns=headers)
Run Code Online (Sandbox Code Playgroud)

在控制台输出中看起来像这样:

  Group  Element Case  Score  Evaluation
0     A        1    x   1.40        0.59
1     A        1    y   9.19        0.52
2     A        2    x   8.82        0.80
3     A        2    y   7.18        0.41
4     B        1    x   1.38        0.22
5     B        1    y   7.14        0.10
6     B        2    x   9.12        0.28
7     B        2    y   4.11        0.97
Run Code Online (Sandbox Code Playgroud)

问题

我想对其执行分组和聚合操作,df这将给出以下结果数据帧:

  Group  Max_score_value  Max_score_element  Max_score_case  Min_evaluation
0     A             9.19                  1               y            0.41 
1     B             9.12                  2               x            0.10
Run Code Online (Sandbox Code Playgroud)

为了更详细地澄清:我想按列分组Group,然后应用聚合来获取以下结果列:

  • Max_score_value:列中的组最大值Score
  • Max_score_elementElement:与组最大值对应的列中的值Score
  • Max_score_caseCase:与组最大值对应的列中的值Score
  • Min_evaluation:列中的组最小值Evaluation

到目前为止尝试过

我提出了以下用于分组和聚合的代码:

result = (
    df.set_index(['Element', 'Case'])
    .groupby('Group')
    .agg({'Score': ['max', 'idxmax'], 'Evaluation': 'min'})
    .reset_index()
)
print(result)
Run Code Online (Sandbox Code Playgroud)

输出为:

  Group Score         Evaluation
          max  idxmax        min
0     A  9.19  (1, y)       0.41
1     B  9.12  (2, x)       0.10
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,基本数据已经存在,但还不是我需要的格式。这是我正在努力解决的最后一步。这里有人有一些关于以我正在寻找的格式生成结果数据框的好主意吗?

Psi*_*dom 4

result数据框开始,您可以按照以下两步转换为您需要的格式:

\n\n
# collapse multi index column to single level column\nresult.columns = [y + '_' + x if y != '' else x for x, y in result.columns]\n\xe2\x80\x8b\n# split the idxmax column into two columns\nresult = result.assign(\n    max_score_element = result.idxmax_Score.str[0],\n    max_score_case = result.idxmax_Score.str[1]\n).drop('idxmax_Score', 1)\n\nresult\n\n#Group  max_Score   min_Evaluation  max_score_case  max_score_element\n#0   A       9.19             0.41               y                  1\n#1   B       9.12             0.10               x                  2\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

另一种从原始dfusing开始的替代方案join,可能不如 @tarashypka 的想法有效,但更简洁:

\n\n
(df.groupby('Group')\n   .agg({'Score': 'idxmax', 'Evaluation': 'min'})\n   .set_index('Score')\n   .join(df.drop('Evaluation',1))\n   .reset_index(drop=True))\n\n#Evaluation  Group  Element   Case  Score\n#0     0.41      A        1      y   9.19\n#1     0.10      B        2      x   9.12\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

使用示例数据集的朴素计时:

\n\n
%%timeit \n(df.groupby('Group')\n .agg({'Score': 'idxmax', 'Evaluation': 'min'})\n .set_index('Score')\n .join(df.drop('Evaluation',1))\n .reset_index(drop=True))\n# 100 loops, best of 3: 3.47 ms per loop\n\n%%timeit\nresult = (\n    df.set_index(['Element', 'Case'])\n    .groupby('Group')\n    .agg({'Score': ['max', 'idxmax'], 'Evaluation': 'min'})\n    .reset_index()\n)\n\xe2\x80\x8b\nresult.columns = [y + '_' + x if y != '' else x for x, y in result.columns]\n\xe2\x80\x8b\nresult = result.assign(\n    max_score_element = result.idxmax_Score.str[0],\n    max_score_case = result.idxmax_Score.str[1]\n).drop('idxmax_Score', 1)\n# 100 loops, best of 3: 7.61 ms per loop\n
Run Code Online (Sandbox Code Playgroud)\n

  • 哦,显式设置索引并在之后加入是一个很好的改进。 (2认同)