我使用python 3。我有熊猫数据帧df。Df看起来像
Name Maths Science Social studies
abc 80 70 90
cde 90 60 80
xyz 100 80 85
...
...
我想生成一个pandas数据框架,它将存储学生姓名,最大分数&这门课得分最高。如果最高分数是100,那么它将考虑下一个最高分数,而不是100。所以我的输出数据帧看起来像
Name Highest_Marks Subject_contributed_Max
abc 90 Social Studies
cde 90 Maths
xyz 85 Social Studies
你能建议我怎么做吗?您可以使用:
df2 = df.drop(columns='Name').mask(df.eq(100))
df['Highest_Marks'] = df2.max(axis=1)
df['Subject_contributed_Max'] = df2.idxmax(axis=1)
输出:
Name Maths Science Social studies Highest_Marks Subject_contributed_Max
0 abc 80 70 90 90.0 Social studies
1 cde 90 60 80 90.0 Maths
2 xyz 100 80 85 85.0 Social studies
为了提高效率,避免计算max/idxmax的两倍,您可以计算idxmax
并使用查找
s = (df
.drop(columns='Name')
.mask(df.eq(100))
.idxmax(axis=1)
)
idx, cols = pd.factorize(s)
df['Highest_Marks'] = df.reindex(cols, axis=1).to_numpy()[np.arange(len(df)), idx]
df['Subject_contributed_Max'] = s
可以了
df_melt = df.melt('Name')
df_melt = df_melt.loc[df_melt['value'] < 100]
df_melt['RN'] = df_melt.sort_values(['value'], ascending=False).groupby(['Name']).cumcount() + 1
df_melt.loc[df_melt['RN'] == 1].sort_values('Name')
可以这样做:
df = df.set_index('Name').stack().reset_index().rename(columns={
'level_1':'Subject_contributed_Max', 0:'Highest_Marks'}).sort_values(
['Name','Highest_Marks'])
df = df[df['Highest_Marks'] != 100].groupby('Name').last().reset_index()[[
'Name', 'Highest_Marks', 'Subject_contributed_Max']]
输入:
Name Maths Science Social studies
0 abc 80 70 90
1 cde 90 60 80
2 xyz 100 80 85
输出:
Name Highest_Marks Subject_contributed_Max
0 abc 90 Social studies
1 cde 90 Maths
2 xyz 85 Social studies
更新:
这里有一个比我原来的答案更快的方法。它类似于@mozway的答案中的一个建议,尽管它使用where()
而不是mask()
(并且它也只返回高分,而不是单个标记列)。
df2 = df.set_index('Name')
df2 = df2.where(df2 < 100)
df2 = df2.assign(**{'Highest_Marks':df2.max(axis=1).astype(int),
'Subject_contributed_Max':df2.idxmax(axis=1)}).reset_index()[[
'Name', 'Highest_Marks', 'Subject_contributed_Max']]
在OP的评论下,我对@mozway和我的答案进行了一些基准测试(我还尝试添加@ArchAngelPwn的答案,但它似乎没有在当前形式下给出可比的输出)。
下面是一个1000行9000列的数据框的结果:
Timeit results:
foo_1 (orig) ran in 2.4102477666456252 seconds using 3 iterations
foo_2 (refined) ran in 2.256996333327455 seconds using 3 iterations
foo_3 (where) ran in 1.1588773333545153 seconds using 3 iterations
foo_4 (mozway mask) ran in 1.17148056665125 seconds using 3 iterations
foo_5 (mozway mask lookup) ran in 1.1049298333236948 seconds using 3 iterations