从 Pandas 数据框中删除“主导”行(所有值都低于任何其他行的值的行)

2024-01-12

编辑:为了清楚起见更改了示例 df

我有一个数据框,类似于下面给出的数据框(除了真实的数据框有几千行和列,并且值是浮点数):

df = pd.DataFrame([[6,5,4,3,8], [6,5,4,3,6], [1,1,3,9,5], [0,1,2,7,4], [2, 0, 0, 4, 0])

    0   1   2   3   4
0   6   5   4   3   8
1   6   5   4   3   6
2   1   1   3   9   5
3   0   1   2   7   4
4   2   0   0   4   0

从这个数据框中,我想删除所有值都低于或等于任何其他行的所有行。对于这个简单的示例,应删除第 1 行和第 3 行(分别由第 0 行和第 2 行“主导”):

filtered df:
    0   1   2   3   4
0   6   5   4   3   8
2   1   1   3   9   5
4   2   0   0   4   0

如果该方法可以考虑浮点错误,那就更好了,因为我的真实数据帧包含浮点数(即,不要删除所有值都较低/相等的行,这些值不应低于少量(例如 0.0001 )。

我最初解决这个问题的想法如下:

  1. 选择第一行
  2. 使用列表理解将其他行与它进行比较(见下文)
  3. 删除所有返回 True 的行
  4. 对下一行重复此操作

列表理解代码:

selected_row = df.loc[0
[(df.loc[r]<=selected_row).all() and (df.loc[r]<selected_row).any() for r in range(len(df))]
[False, True, False, False, False]

然而,这似乎效率不高。任何有关如何(有效)解决此问题的建议将不胜感激。


我们可以尝试broadcasting https://numpy.org/doc/stable/user/basics.broadcasting.html:

import pandas as pd

df = pd.DataFrame([
    [6, 5, 4, 3, 8], [6, 5, 4, 3, 6], [1, 1, 3, 9, 5],
    [0, 1, 2, 7, 4], [2, 0, 0, 4, 0]
])

# Need to ensure only one of each row present since comparing to 1
# there needs to be one and only one of each row
df = df.drop_duplicates()

# Broadcasted comparison explanation below
cmp = (df.values[:, None] <= df.values).all(axis=2).sum(axis=1) == 1

# Filter using the results from the comparison
df = df[cmp]

df:

   0  1  2  3  4
0  6  5  4  3  8
2  1  1  3  9  5
4  2  0  0  4  0

直觉:

通过 DataFrame 广播比较操作:

(df.values[:, None] <= df.values)
[[[ True  True  True  True  True]
  [ True  True  True  True False]
  [False False False  True False]
  [False False False  True False]
  [False False False  True False]]  # df vs [6 5 4 3 8]

 [[ True  True  True  True  True]
  [ True  True  True  True  True]
  [False False False  True False]
  [False False False  True False]
  [False False False  True False]]  # df vs [6 5 4 3 6]

 [[ True  True  True False  True]
  [ True  True  True False  True]
  [ True  True  True  True  True]
  [False  True False False False]
  [ True False False False False]]  # df vs [1 1 3 9 5]

 [[ True  True  True False  True]
  [ True  True  True False  True]
  [ True  True  True  True  True]
  [ True  True  True  True  True]
  [ True False False False False]]  # df vs [0 1 2 7 4]

 [[ True  True  True False  True]
  [ True  True  True False  True]
  [False  True  True  True  True]
  [False  True  True  True  True]
  [ True  True  True  True  True]]]  # df vs [2 0 0 4 0]

然后我们可以检查all https://numpy.org/doc/stable/reference/generated/numpy.ndarray.all.html on axis=2:

(df.values[:, None] <= df.values).all(axis=2)
[[ True False False False False]   # Rows le [6 5 4 3 8]
 [ True  True False False False]   # Rows le [6 5 4 3 6]
 [False False  True False False]   # Rows le [1 1 3 9 5]
 [False False  True  True False]   # Rows le [0 1 2 7 4]
 [False False False False  True]]  # Rows le [2 0 0 4 0]

然后我们可以使用sum https://numpy.org/doc/stable/reference/generated/numpy.ndarray.sum.html总计有多少行小于或等于:

(df.values[:, None] <= df.values).all(axis=2).sum(axis=1)
[1 2 1 2 1]

只有 1 行小于或等于(仅自匹配)的行是要保留的行。因为我们drop_duplicates https://pandas.pydata.org/docs/reference/api/pandas.Series.drop_duplicates.html数据框中不会有重复项,因此唯一的True值将是自我匹配以及小于或等于的值:

(df.values[:, None] <= df.values).all(axis=2).sum(axis=1) == 1
[ True False  True False  True]

然后,这将成为 DataFrame 的过滤器:

df = df[[True, False, True, False, True]]

df:

   0  1  2  3  4
0  6  5  4  3  8
2  1  1  3  9  5
4  2  0  0  4  0
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 Pandas 数据框中删除“主导”行(所有值都低于任何其他行的值的行) 的相关文章

随机推荐