86

我正在使用groupbypandas 数据框来删除所有没有特定列最小值的行。像这样的东西:

df1 = df.groupby("item", as_index=False)["diff"].min()

但是,如果我有两个以上的列,则其他列(例如otherstuff在我的示例中)将被删除。我可以使用 保留这些列groupby,还是必须找到一种不同的方法来删除行?

我的数据看起来像:

    item    diff   otherstuff
   0   1       2            1
   1   1       1            2
   2   1       3            7
   3   2      -1            0
   4   2       1            3
   5   2       4            9
   6   2      -6            2
   7   3       0            0
   8   3       2            9

最终应该像:

    item   diff  otherstuff
   0   1      1           2
   1   2     -6           2
   2   3      0           0

但我得到的是:

    item   diff
   0   1      1           
   1   2     -6           
   2   3      0                 

我一直在查看文档,但找不到任何东西。我试过了:

df1 = df.groupby(["item", "otherstuff"], as_index=false)["diff"].min()

df1 = df.groupby("item", as_index=false)["diff"].min()["otherstuff"]

df1 = df.groupby("item", as_index=false)["otherstuff", "diff"].min()

但是这些都不起作用(我意识到最后一个语法是用于在创建组后进行聚合)。

4

5 回答 5

151

方法#1:用于idxmin()获取minimum 元素的索引diff,然后选择那些:

>>> df.loc[df.groupby("item")["diff"].idxmin()]
   item  diff  otherstuff
1     1     1           2
6     2    -6           2
7     3     0           0

[3 rows x 3 columns]

方法#2:按 排序diff,然后取每组的第一个元素item

>>> df.sort_values("diff").groupby("item", as_index=False).first()
   item  diff  otherstuff
0     1     1           2
1     2    -6           2
2     3     0           0

[3 rows x 3 columns]

请注意,即使行内容相同,生成的索引也不同。

于 2014-04-30T17:43:00.297 回答
12

您可以DataFrame.sort_values使用DataFrame.drop_duplicates

df = df.sort_values(by='diff').drop_duplicates(subset='item')
print (df)
   item  diff  otherstuff
6     2    -6           2
7     3     0           0
1     1     1           2

如果可能,每组有多个最小值,并希望所有最小行使用boolean indexingwithtransform来表示每组的最小值:

print (df)
   item  diff  otherstuff
0     1     2           1
1     1     1           2 <-multiple min
2     1     1           7 <-multiple min
3     2    -1           0
4     2     1           3
5     2     4           9
6     2    -6           2
7     3     0           0
8     3     2           9

print (df.groupby("item")["diff"].transform('min'))
0    1
1    1
2    1
3   -6
4   -6
5   -6
6   -6
7    0
8    0
Name: diff, dtype: int64

df = df[df.groupby("item")["diff"].transform('min') == df['diff']]
print (df)
   item  diff  otherstuff
1     1     1           2
2     1     1           7
6     2    -6           2
7     3     0           0
于 2019-01-08T07:43:51.040 回答
1

如果有/您想要一分钟,上述答案效果很好。在我的情况下,可能有多个分钟,我希望所有行都等于 min,这.idxmin()不会给你。这有效

def filter_group(dfg, col):
    return dfg[dfg[col] == dfg[col].min()]

df = pd.DataFrame({'g': ['a'] * 6 + ['b'] * 6, 'v1': (list(range(3)) + list(range(3))) * 2, 'v2': range(12)})
df.groupby('g',group_keys=False).apply(lambda x: filter_group(x,'v1'))

顺便说一句,.filter()也与这个问题有关,但对我不起作用。

于 2018-03-25T13:04:15.417 回答
1

我尝试了每个人的方法,但我无法让它正常工作。相反,我一步一步地完成了这个过程,最终得到了正确的结果。

df.sort_values(by='item', inplace=True, ignore_index=True)
df.drop_duplicates(subset='diff', inplace=True, ignore_index=True)
df.sort_values(by=['diff'], inplace=True, ignore_index=True)

更多解释:

  1. 按您想要的最小值对项目进行排序
  2. 删除要排序的列的重复项
  3. 重新排序数据,因为数据仍按最小值排序
于 2021-06-18T01:25:45.023 回答
-1

如果您知道您的所有“项目”都有多个可以排序的记录,请使用duplicated

df.sort_values(by='diff').duplicated(subset='item', keep='first')
于 2018-09-17T22:01:59.707 回答