pandas 在“groupby”和计算后保留所需的列

xqk2d5yq  于 2022-12-16  发布在  其他
关注(0)|答案(3)|浏览(248)

如果我有一张考试成绩表,想知道每个科目谁最好谁最差。
输入表的示例:
| 主题|得分|姓名|
| - ------|- ------|- ------|
| 数学|二十七|学生1|
| 历史|四十三|学生2|
| 数学|四十四|学生3|
| 历史|五十|学生1|
| 科学类|七|学生1|
| 历史记录|十个|学生3|
| 科学|四十三|学生2|
我想使输出表如下表:
| 主题|最佳评分|最佳种马|最差Scr|最差螺柱|
| - ------|- ------|- ------|- ------|- ------|
| 数学|四十四|学生3|二十七|学生1|
| 历史|五十|学生1|十个|学生3|
| 科学|四十三|学生2|七|学生1|
下面的代码是我尝试:

inputTableGrouped = inputTable.groupby(['Subject'])

outputTableGrouped['BestScr'] = inputTableGrouped.Score.max()
outputTableGrouped['WorstScr'] = inputTableGrouped.Score.min()

outputTable = outputTableGrouped.reset_index()

但是这样的话,我找不到记录学生姓名的方法,我该怎么做呢?

kkbh8khc

kkbh8khc1#

您可以将GroupBy.aggDataFrameGroupBy.idxmaxDataFrameGroupBy.idxmin一起用于按最大和最小Score的索引,并使用DataFrame.loc选择匹配行,使用DataFrame.add_prefixSubject转换为索引,然后连接在一起:

df1 = df.groupby('Subject', sort=False)['Score'].agg(['idxmin','idxmax'])

df11 = df.loc[df1['idxmax']].set_index('Subject').add_prefix('Best')
df22 = df.loc[df1['idxmin']].set_index('Subject').add_prefix('Worst')

df = df11.join(df22).reset_index()
print (df)
   Subject  BestScore  BestName  WorstScore WorstName
0     Math         44  Student3          27  Student1
1  History         50  Student1          10  Student3
2  Science         43  Student2           7  Student1

或者将Name转换为索引,这样您就可以将GroupBy.aggDataFrameGroupBy.idxmaxDataFrameGroupBy.idxmin以及min一起使用max函数:

df = (df.set_index('Name')
        .groupby('Subject', as_index=False, sort=False)
        .agg(BestScr=('Score', 'max'),
            BestStud= ('Score', 'idxmax'),
            WorstScr=('Score', 'min'),
            WorstStud=('Score', 'idxmax'))
)
print (df)
   Subject  BestScr  BestStud  WorstScr WorstStud
0     Math       44  Student3        27  Student3
1  History       50  Student1        10  Student1
2  Science       43  Student2         7  Student2
jyztefdp

jyztefdp2#

您可以使用自定义groupby.agg

(df.groupby('Subject', as_index=False, sort=False)
    .agg(**{'BestScr': ('Score', 'max'),
            'BestStd': ('Score', lambda s: df.loc[s.idxmax(), 'Name']),
            'WorstScr': ('Score', 'min'),
            'WorstStd': ('Score', lambda s: df.loc[s.idxmin(), 'Name']),
                            })
)

输出:

Subject  BestScr   BestStd  WorstScr  WorstStd
0     Math       44  Student3        27  Student1
1  History       50  Student1        10  Student3
2  Science       43  Student2         7  Student1
tzdcorbm

tzdcorbm3#

另一种可能的解决方案基于pandas.DataFrame.unstack

out = df.set_index(['Subject', 'Name'])['Score'].unstack()
out['BestScr'], out['BestStud'], out['WorstScr'], out['WorstStud'] = out.max(
    1), out.idxmax(1), out.min(1), out.idxmin(1)
out = out.drop(columns=out.columns[out.columns.str.startswith('Student')])
out = out.rename_axis(None, axis=1).reset_index()

输出:

Subject  BestScr  BestStud  WorstScr WorstStud
0  History     50.0  Student1      10.0  Student3
1     Math     44.0  Student3      27.0  Student1
2  Science     43.0  Student2       7.0  Student1

相关问题