Pandas删除值小于给定值的行

4
我希望删除只包含小于10和大于25的值的行。我的样本数据框如下所示:
a   b   c  
1   2   3  
4   5   16  
11  24  22  
26  50  65  

期望输出:

a   b   c  
1   2   3  
4   5   16   
26  50  65  

如果行中包含任何小于 10 或大于 25 的值,则该行将保留在数据框中,否则需要将其删除。

有没有办法使用 Pandas 实现此操作,而不是遍历所有行?


祝你好运。希望你能处理好你的行。 - Mad Physicist
1
只是提醒一下,这不是你在SO上提问的方式。你应该展示出一些自己的最小努力。如果你有资源在这里提问,那么你也有资源自己进行一些搜索。 - Mad Physicist
为什么你期望的输出中仍然包含第一行和最后一行?这毫无意义。 - Paul H
如果行中有任何一个值小于10或大于25,则该行将保留在数据框中,否则需要删除。 - Jaswanth Kumar
这已经澄清了,但是问题的结尾与开头相矛盾。 - Paul H
显示剩余2条评论
3个回答

6
您可以调用apply并将结果返回到名为“Keep”的新列中。然后,您可以使用此列删除不需要的行。
import pandas as pd
l = [[1,2,3],[4,5,6],[11,24,22],[26,50,65]]
df = pd.DataFrame(l, columns = ['a','b','c']) #Set up sample dataFrame

df['keep'] = df.apply(lambda row: sum(any([(x < 10) or (x > 25) for x in row])), axis = 1)
any()函数返回一个生成器。调用sum(generator)只会返回生成器中所有结果的总和。
查看this以了解any()的工作原理。 应用函数仍然像for循环一样迭代所有行,但是这种方式的代码看起来更加简洁。我想不出一种在不迭代所有行的情况下完成此操作的方法。
输出:
    a   b   c  keep
0   1   2   3     1
1   4   5   6     1
2  11  24  22     0
3  26  50  65     1


df = df[df['keep'] == 1] #Drop unwanted rows

很好的答案!我对pandas不太熟悉,想知道“只是循环”遍历DataFrame是否更有效率。我不知道panda的数据框在底层是如何实现的,但这似乎要重复遍历两次。 你能否指引一些相关解释给我呢? - mimre
应用函数只是一个循环的语法糖。即使你编写了一个for循环来遍历所有行,我也不确定是否有一种方法可以动态删除行。 - Rakesh Adhikesavan

5

你可以使用pandas布尔索引

dropped_df = df.loc[((df<10) | (df>25)).any(1)]
  • df<10会返回一个布尔值数据框
  • |是OR运算符
  • .any(1)返回轴1(行)上的任何真元素 请参阅文档
  • df.loc[]然后根据布尔值数据框过滤数据框

1

我非常喜欢像这样使用掩码;它很干净,以便您可以回到代码中阅读。它比使用.apply更快,后者实际上是循环。此外,它避免了设置复制警告。

这使用布尔索引,就像Prageeth的答案一样。但不同之处在于,我喜欢如何将布尔索引保存为单独的变量以供稍后重复使用。我经常这样做,这样我就不必修改原始数据框或创建一个新的数据框,只需在需要截取数据框视图的地方使用df[mask]即可。

df = pd.DataFrame(
    [[1,2,3],
    [4,5,16],
    [11,24,22],
    [26,50,65]],
    columns=['a','b','c']
)

#use a mask to create a fully indexed boolean dataframe, 
#which avoids the SettingWithCopyWarning:
#https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
mask = (df > 10) & (df < 25)
print(mask)
"""
       a      b      c
0  False  False  False
1  False  False   True
2   True   True   True
3  False  False  False
"""

print(df[mask])
"""
      a     b     c
0   NaN   NaN   NaN
1   NaN   NaN  16.0
2  11.0  24.0  22.0
3   NaN   NaN   NaN
"""

print(df[mask].dropna())
"""
      a     b     c
2  11.0  24.0  22.0
"""

#one neat things about using masking is you can invert them too with a '~'
print(~mask)
"""
       a      b      c
0   True   True   True
1   True   True  False
2  False  False  False
3   True   True   True
"""

print( df[~mask].dropna())
"""
      a     b     c
0   1.0   2.0   3.0
3  26.0  50.0  65.0
"""

#you can also combine masks
mask2 = mask & (df < 24)
print(mask2)
"""
       a      b      c
0  False  False  False
1  False  False   True
2   True  False  False
3  False  False  False
"""

#and the resulting dataframe (without dropping the rows that are nan or contain any false mask)
print(df[mask2])
"""
      a   b     c
0   NaN NaN   NaN
1   NaN NaN  16.0
2  11.0 NaN  22.0
3   NaN NaN   NaN
"""

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