Pandas:根据条件删除多行

4
以下是我拥有的 pandas dataframe 的一个子集,我正在尝试根据某些条件删除多行。
  code1 code2 grp1 grp2  dist_km
0  M001  M002  AAA  AAA      112
1  M001  M003  AAA  IHH      275
2  M002  M005  AAA  XXY      150
3  M002  M004  AAA  AAA       65
4  M003  M443  IHH  GRR       50
5  M003  M667  IHH  IHH      647
6  M003  M664  IHH  FFG      336

我只想保留那些在每个code1中,grp1grp2相同且dist_km是特定code1中最小的值所在行。

对于上面的示例,只有以下行将保留:

  code1 code2 grp1 grp2  dist_km
0  M001  M002  AAA  AAA      112
3  M002  M004  AAA  AAA       65

什么是最简单的方法来完成这个任务?

1
M003 M667 IHH IHH 647 是否也在您所需的数据框中? - Joe Patten
请澄清您的问题。有3行满足grp1==grp2且没有相同的code1。 - Kyle
不,对于 M003,最小的 dist_km50,并且由于该行的 grp1grp2 不相等,所有 M003 的行都需要被删除。 - Funkeh-Monkeh
5个回答

5

使用 sort_valuesdrop_duplicates 不需要使用 groupby

df.sort_values('dist_km').drop_duplicates('code1').query('grp1==grp2')
  code1 code2 grp1 grp2  dist_km
3  M002  M004  AAA  AAA       65
0  M001  M002  AAA  AAA      112

4

使用两个条件

df.loc[(df['dist_km'] == df.groupby('code1')['dist_km'].transform('min')) & (df['grp1'] == df['grp2'])]

    code1   code2   grp1    grp2    dist_km
0   M001    M002    AAA     AAA     112
3   M002    M004    AAA     AAA     65

1
你可以在转换后使用查询进行过滤。 - BENY
@W-B,我对查询还不是很熟悉。这两种方法的性能有区别吗? - Vaishali
1
至少缩短你的代码 :-) 也可以参考 https://jakevdp.github.io/PythonDataScienceHandbook/03.12-performance-eval-and-query.html - BENY

2
如果创建临时数据框不是问题,那么你可以尝试使用transform:最初的回答。
tmp = df[df.groupby('code1')['dist_km'].transform('min') == df['dist_km']]
df1 = tmp[tmp['grp1'] == tmp['grp2']]

最初的回答是:或者您也可以尝试以下方法:
new_df = df.loc[df.groupby('code1')['dist_km'].idxmin()][df['grp1']==df['grp2']]

0

这是一种通过链接一系列条件来实现的方法。我已经对它们进行了注释,以便在每个步骤中都清晰明了(顺序很重要):

codes = df.code1.unique()     # gets unique codes
splitdfs = []

for code in codes:
    tempdf = df[df.code1 == code]                            # select all code1
    tempdf = tempdf[tempdf.dist_km == tempdf.dist_km.min()]  # select dist_km is min
    tempdf = tempdf[tempdf.grp1 == tempdf.grp2]              # select grp1 == grp2 (must be AFTER selecting lowest dist_km)

    splitdfs.append(tempdf)


selectdf = pd.concat(splitdfs)


0
你可以通过对数据框进行筛选、应用 groupby/agg 然后合并回来来实现这一点。
result_df = df.loc[df.grp1 == df.grp2].groupby('code1').agg({'dist_km': min})
df = pd.merge(df, result_df, how='inner', 
              left_on=['code1', 'dist_km'], right_on=['code1', 'dist_km'])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接