熊猫groupby,然后按列值(例如,最小值,最大值)选择一行

时间:2019-03-15 15:47:53

标签: python pandas aggregate

假设我有一个数据框

Category Data1 column1
A 'SOMEDATA' 10
A 'SOMEDATA' 2
A 'SOMEDATA' -10
B 'SOMEDATA' 10
B 'SOMEDATA' 1
B 'SOMEDATA' -10

以此类推

我想按列值在每个组中选择一行。例如,ABS(column1)

因此得出的数据是

Category Data1 column1
A 'SOMEDATA' 2
B 'SOMEDATA'  1

如何在python中做到这一点?

我不知道如何返回整行。例如,

df.groupby('Category')['column1'].min();

这只会返回“ Category” min(column1)。

3 个答案:

答案 0 :(得分:1)

sort,然后是.drop_duplicates,如果要基于绝对值的单个最小行。

(df.assign(to_sort = df.column1.abs()).sort_values('to_sort')
     .drop_duplicates('Category').drop(columns='to_sort'))

  Category       Data1  column1
4        B  'SOMEDATA'        1
1        A  'SOMEDATA'        2

排序只能对现有列进行排序,因此我们需要创建绝对值列(使用.assign)。然后排序将确保最小绝对值首先出现,并且删除重复项将保留每个类别的第一行,现在是最小绝对值行。

groupby也可以,如果每个组需要返回多个行,则更好:

df.assign(to_sort = df.column1.abs()).sort_values('to_sort').groupby(df.Category).head(1)

或者,您可以使用groupby的结果进行切片。如果要返回与最小值匹配的所有所有行,这很有用:

df[df.groupby(df.Category, group_keys=False).apply(lambda x: x.column1 == x.column1.abs().min())]

  Category       Data1  column1
1        A  'SOMEDATA'        2
4        B  'SOMEDATA'        1

答案 1 :(得分:0)

您可以使用绝对值创建其他列,然后使用最小值创建loc

df['absValues'] = df.column1.abs()
df.loc[df['absValues'] == df.groupby('Category')['absValues'].transform('min')]
.drop_duplicates(['Category']).drop('absValues', 1)

out
    Category    Data1   column1
1   A   'SOMEDATA'  2
4   B   'SOMEDATA'  1

这样,您将为DataFrame中的每一行保留所有其他列。

如果需要在每个组中返回所有等于min的值,请从代码中删除.drop_duplicates()

答案 2 :(得分:0)

这是一种计算效率更高的解决方案。

TL; DR版本

df.loc[df.groupby('Category')['column1'].idxmin()]