Pandas GroupBy 并选择特定列中具有最小值的行

Wen*_*ndy 19 python group-by pandas pandas-groupby

我按 A 列对我的数据集进行分组,然后想取 B 列中的最小值和 C 列中的相应值。

data = pd.DataFrame({'A': [1, 2], 'B':[ 2, 4], 'C':[10, 4]})
data  
    A   B   C
0   1   4   3
1   1   5   4
2   1   2   10
3   2   7   2
4   2   4   4
5   2   6   6  
Run Code Online (Sandbox Code Playgroud)

我想得到:

    A   B   C
0   1   2   10
1   2   4   4
Run Code Online (Sandbox Code Playgroud)

目前我按 A 分组,并创建一个值来指示我将保留在我的数据集中的行:

a = data.groupby('A').min()
a['A'] = a.index
to_keep = [str(x[0]) + str(x[1]) for x in a[['A', 'B']].values]
data['id'] = data['A'].astype(str) + data['B'].astype('str')
data[data['id'].isin(to_keep)]
Run Code Online (Sandbox Code Playgroud)

我相信有一种更直接的方法可以做到这一点。我在这里看到了很多使用多索引的答案,但我想这样做而不向我的数据帧添加多索引。感谢您的帮助。

cs9*_*s95 27

感觉你多虑了 只需使用groupbyidxmin

df.loc[df.groupby('A').B.idxmin()]

   A  B   C
2  1  2  10
4  2  4   4
Run Code Online (Sandbox Code Playgroud)
df.loc[df.groupby('A').B.idxmin()].reset_index(drop=True)

   A  B   C
0  1  2  10
1  2  4   4
Run Code Online (Sandbox Code Playgroud)

  • @cs95,这会导致每个 A 一行,如果有多行 A 中每个值的最小值怎么办?就像所有在科学中获得最低分数的学生一样。 (5认同)

小智 14

有类似的情况,但具有更复杂的列标题(例如“B val”),在这种情况下需要:

df.loc[df.groupby('A')['B val'].idxmin()]
Run Code Online (Sandbox Code Playgroud)


Myk*_*tko 6

您可以sort_values并且drop_duplicates

df.sort_values('B').drop_duplicates('A')
Run Code Online (Sandbox Code Playgroud)

输出:

   A  B   C
2  1  2  10
4  2  4   4
Run Code Online (Sandbox Code Playgroud)


kra*_*ski 5

接受的答案(建议idxmin)不能与管道模式一起使用。管道友好的替代方案是首先对值进行排序,然后使用groupbywith DataFrame.head

data.sort_values('B').groupby('A').apply(DataFrame.head, n=1)
Run Code Online (Sandbox Code Playgroud)

这是可能的,因为默认情况下groupby 会保留每个组中行的顺序,这是稳定且有记录的行为(请参阅 参考资料pandas.DataFrame.groupby)。

这种方法还有其他好处:

  • 它可以轻松扩展以选择特定列中具有最小值的n行
  • 它可以通过向 提供另一列(作为列表)来打破联系.sort_values(),例如:
    data.sort_values(['final_score', 'midterm_score']).groupby('year').apply(DataFrame.head, n=1)
    
    Run Code Online (Sandbox Code Playgroud)

与其他答案一样,为了完全匹配问题中所需的结果.reset_index(drop=True),需要制作最终的片段:

df.sort_values('B').groupby('A').apply(DataFrame.head, n=1).reset_index(drop=True)
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。我会补充说我是这样做的,并且似乎以同样的方式工作:`data.sort_values('B').groupby('A').head(1)` (2认同)