在数据帧中查找重复项并仅保留最高的重复项

Find duplicates in dataframe and keep only the highest ones

提问人:Alex Bejan 提问时间:11/11/2021 最后编辑:Alex Bejan 更新时间:11/11/2021 访问量:168

问:

我正在尝试在数据帧中查找每个组较高的重复项,以便稍后可以根据索引从另一个数据帧中删除这些重复项,以便主数据帧没有重复项,只有最低值。

基本上,假设我们有这个数据帧:

index   group   value
  1       1      402
  2       1      396
  3       2      406
  4       2      416
  5       2      407
  6       2      406
  7       1      200
  8       2      350

我需要的是只保留每组具有最高值的连续重复项中的重复项,并删除最低值的重复项。该组为 1 或 2,但同一组中可以有多个连续值的实例。 因此,生成的数据帧将是:

index   group   value
  1       1      402
  4       2      416
  5       2      407

速度也很重要,不能向前看。

Python Pandas DataFrame CSV 数据操作

评论

0赞 Joshua Voskamp 11/11/2021
它需要保持原始订单/索引吗?
0赞 Joshua Voskamp 11/11/2021
从您给出的结果来看,您似乎只想删除每个组中的最低值(如果有多个值)?
1赞 Joshua Voskamp 11/11/2021
鉴于 OP 的描述(尽管有限且令人困惑?),这似乎是相关的
1赞 Joshua Voskamp 11/11/2021
如果@HarryPlotter和我正确地理解了意图,请编辑这个问题的标题,以更准确地反映意图。
1赞 Alex Bejan 11/11/2021
我已经更新了描述,希望它更有意义

答:

1赞 Rodalm 11/11/2021 #1

使用 + 屏蔽每个组的最小值。然后使用蒙版仅选择所需的行。groupbytransform

# map each consecutive group of rows to a different integer
group_labels = (df.group != df.group.shift()).cumsum()

# find the minimum value of each group 
group_min_val = df.groupby(group_labels)['value'].transform('min')

# get only the rows of each group whose value is higher than the minimum 
res = df[df.value != group_min_val]

>>> res

   index  group  value
0      1      1    402
3      4      2    416
4      5      2    407

中间结果


>>> group_labels

0    1
1    1
2    2
3    2
4    2
5    2
6    3
7    4
Name: group, dtype: int64

>>> group_min_val

0    396
1    396
2    406
3    406
4    406
5    406
6    200
7    350
Name: value, dtype: int64

>>> df.value != group_min_val

0     True
1    False
2    False
3     True
4     True
5    False
6    False
7    False
Name: value, dtype: bool

评论

0赞 Alex Bejan 11/11/2021
问题是你可以有多个组,所以这会把它们全部分组,我需要的是每个组集中的最小值。我已经更新了数据帧
0赞 Joshua Voskamp 11/11/2021
@AlexBejan你说的“群体”是什么意思?
1赞 Rodalm 11/11/2021
@AlexBejan我已经更新了答案。这是你要找的吗?
1赞 Rodalm 11/11/2021
@JoshuaVoskamp我知道这一点,但老实说,我更喜欢这种方式,我认为它更具可读性!但这只是一个偏好问题
1赞 Alex Bejan 11/11/2021
太好了,工作起来很有魅力,谢谢先生!
1赞 Joshua Voskamp 11/11/2021 #2

@HarryPlotter 的回答的单行版本:

df.loc[df.value.ne(df.groupby(df.group.ne(df.group.shift()).cumsum()).value.transform('min'))]

使用这里的技巧来应用OP对“分组”的理解,并进行转换以获得每个组中的最小值,然后对所有不等于这些值的值进行-ing。.loc

警告:这会删除任何单例“组”!(如果 OP 的注释表明“保持除最低值之外的所有值”,则丢弃了从技术上讲也是其组中“最高”的单例值。

1赞 Алексей Р 11/11/2021 #3

使用 rank() 可以更容易地做到这一点。
在这种情况下,您需要决定如何处理相同的最小值 - 删除其中一个 () 或两个 ()。根据解决方案集中的条件“删除最低的”:
method = 'first'method = 'min'method = 'first'

df = pd.DataFrame({'index': [1, 2, 3, 4, 5, 6, 7], 'group': [1, 1, 2, 2, 2, 1, 2],
                   'value': [402, 396, 406, 416, 407, 200, 350]}).set_index('index')
print('Source df:\n', df)
df = df[df.groupby(df.group.diff().ne(0).cumsum())['value'].rank(method='first').gt(1)]
print('\nResult df:\n', df)

输出:

Source df:
        group  value
index              
1          1    402
2          1    396
3          2    406
4          2    416
5          2    407
6          1    200
7          2    350

Result df:
        group  value
index              
1          1    402
4          2    416
5          2    407

评论

0赞 Alex Bejan 11/11/2021
似乎不起作用,它仍然具有组中的所有值
0赞 Алексей Р 11/11/2021
这很奇怪。它对我有用,请参阅上面的完整示例和结果。以防万一,替换为.ne(1).gt(1)
0赞 Alex Bejan 11/11/2021
仍然不适用于我的数据,不知道为什么。我已经接受了@HarryPlotter的解决方案,这很好,无论如何,谢谢
0赞 Алексей Р 11/11/2021
与预期结果不同的原因是,在更新描述后,我没有阅读有关顺序组的说明。代码已更新。
0赞 Alex Bejan 11/11/2021
是的,它现在正在工作,谢谢!