根据列值删除 Pandas 中的 DataFrame 行

2024-12-04 08:56:00
admin
原创
146
摘要:问题描述:我有以下数据框: daysago line_race rating rw wrating line_date 2007-03-31 62 ...

问题描述:

我有以下数据框:

             daysago  line_race rating        rw    wrating
 line_date                                                 
2007-03-31       62         11     56  1.000000  56.000000
2007-03-10       83         11     67  1.000000  67.000000
2007-02-10      111          9     66  1.000000  66.000000
2007-01-13      139         10     83  0.880678  73.096278
2006-12-23      160         10     88  0.793033  69.786942
2006-11-09      204          9     52  0.636655  33.106077
2006-10-22      222          8     66  0.581946  38.408408
2006-09-29      245          9     70  0.518825  36.317752
2006-09-16      258         11     68  0.486226  33.063381
2006-08-30      275          8     72  0.446667  32.160051
2006-02-11      475          5     65  0.164591  10.698423
2006-01-13      504          0     70  0.142409   9.968634
2006-01-02      515          0     64  0.134800   8.627219
2005-12-06      542          0     70  0.117803   8.246238
2005-11-29      549          0     70  0.113758   7.963072
2005-11-22      556          0     -1  0.109852  -0.109852
2005-11-01      577          0     -1  0.098919  -0.098919
2005-10-20      589          0     -1  0.093168  -0.093168
2005-09-27      612          0     -1  0.083063  -0.083063
2005-09-07      632          0     -1  0.075171  -0.075171
2005-06-12      719          0     69  0.048690   3.359623
2005-05-29      733          0     -1  0.045404  -0.045404
2005-05-02      760          0     -1  0.039679  -0.039679
2005-04-02      790          0     -1  0.034160  -0.034160
2005-03-13      810          0     -1  0.030915  -0.030915
2004-11-09      934          0     -1  0.016647  -0.016647

我需要删除line_race等于的行0。最有效的方法是什么?


解决方案 1:

如果我理解正确的话,它应该很简单:

df = df[df.line_race != 0]

解决方案 2:

但是对于任何未来的旁路者,你可以提到,df = df[df.line_race != 0]在尝试过滤None/缺失值时不会执行任何操作。

是否有效:

df = df[df.line_race != 0]

不做任何事情:

df = df[df.line_race != None]

是否有效:

df = df[df.line_race.notnull()]

解决方案 3:

只需添加另一个解决方案,如果您使用新的熊猫评估员,则特别有用,其他解决方案将取代原始的熊猫并失去评估员

df.drop(df.loc[df['line_race']==0].index, inplace=True)

解决方案 4:

如果有多个值和 str dtype

我使用以下方法过滤掉col中的给定值:

def filter_rows_by_values(df, col, values):
    return df[~df[col].isin(values)]

例子:

在 DataFrame 中我想删除列“str”中值为“b”和“c”的行

df = pd.DataFrame({"str": ["a","a","a","a","b","b","c"], "other": [1,2,3,4,5,6,7]})
df
   str  other
0   a   1
1   a   2
2   a   3
3   a   4
4   b   5
5   b   6
6   c   7

filter_rows_by_values(df, "str", ["b","c"])

   str  other
0   a   1
1   a   2
2   a   3
3   a   4

解决方案 5:

如果您想根据列的多个值删除行,您可以使用:

df[(df.line_race != 0) & (df.line_race != 10)]

删除所有值为 0 和 10 的行line_race

解决方案 6:

虽然前面的答案与我要做的几乎相似,但使用索引方法不需要使用另一个索引方法 .loc()。它可以以类似但精确的方式完成

df.drop(df.index[df['line_race'] == 0], inplace = True)

解决方案 7:

最好的方法是使用布尔掩码:

In [56]: df
Out[56]:
     line_date  daysago  line_race  rating    raw  wrating
0   2007-03-31       62         11      56  1.000   56.000
1   2007-03-10       83         11      67  1.000   67.000
2   2007-02-10      111          9      66  1.000   66.000
3   2007-01-13      139         10      83  0.881   73.096
4   2006-12-23      160         10      88  0.793   69.787
5   2006-11-09      204          9      52  0.637   33.106
6   2006-10-22      222          8      66  0.582   38.408
7   2006-09-29      245          9      70  0.519   36.318
8   2006-09-16      258         11      68  0.486   33.063
9   2006-08-30      275          8      72  0.447   32.160
10  2006-02-11      475          5      65  0.165   10.698
11  2006-01-13      504          0      70  0.142    9.969
12  2006-01-02      515          0      64  0.135    8.627
13  2005-12-06      542          0      70  0.118    8.246
14  2005-11-29      549          0      70  0.114    7.963
15  2005-11-22      556          0      -1  0.110   -0.110
16  2005-11-01      577          0      -1  0.099   -0.099
17  2005-10-20      589          0      -1  0.093   -0.093
18  2005-09-27      612          0      -1  0.083   -0.083
19  2005-09-07      632          0      -1  0.075   -0.075
20  2005-06-12      719          0      69  0.049    3.360
21  2005-05-29      733          0      -1  0.045   -0.045
22  2005-05-02      760          0      -1  0.040   -0.040
23  2005-04-02      790          0      -1  0.034   -0.034
24  2005-03-13      810          0      -1  0.031   -0.031
25  2004-11-09      934          0      -1  0.017   -0.017

In [57]: df[df.line_race != 0]
Out[57]:
     line_date  daysago  line_race  rating    raw  wrating
0   2007-03-31       62         11      56  1.000   56.000
1   2007-03-10       83         11      67  1.000   67.000
2   2007-02-10      111          9      66  1.000   66.000
3   2007-01-13      139         10      83  0.881   73.096
4   2006-12-23      160         10      88  0.793   69.787
5   2006-11-09      204          9      52  0.637   33.106
6   2006-10-22      222          8      66  0.582   38.408
7   2006-09-29      245          9      70  0.519   36.318
8   2006-09-16      258         11      68  0.486   33.063
9   2006-08-30      275          8      72  0.447   32.160
10  2006-02-11      475          5      65  0.165   10.698

更新:现在 pandas 0.13 已经发布,另一种实现方法是df.query('line_race != 0')

解决方案 8:

尽管如此,给出的答案是正确的,正如上面有人说的那样,您可以df.query('line_race != 0')根据自己的问题使用哪种方法更快。强烈推荐。

解决方案 9:

有多种方法可以实现这一点。下面将列出各种选项,供您根据用例的具体情况使用。

人们会认为OP的数据框存储在变量中df


选项 1

对于 OP 的情况,考虑到唯一具有值的列0line_race,以下内容将完成工作

 df_new = df[df != 0].dropna()
 
[Out]:
     line_date  daysago  line_race  rating        rw    wrating
0   2007-03-31       62       11.0      56  1.000000  56.000000
1   2007-03-10       83       11.0      67  1.000000  67.000000
2   2007-02-10      111        9.0      66  1.000000  66.000000
3   2007-01-13      139       10.0      83  0.880678  73.096278
4   2006-12-23      160       10.0      88  0.793033  69.786942
5   2006-11-09      204        9.0      52  0.636655  33.106077
6   2006-10-22      222        8.0      66  0.581946  38.408408
7   2006-09-29      245        9.0      70  0.518825  36.317752
8   2006-09-16      258       11.0      68  0.486226  33.063381
9   2006-08-30      275        8.0      72  0.446667  32.160051
10  2006-02-11      475        5.0      65  0.164591  10.698423

然而,由于情况并非总是如此,因此建议检查以下选项,其中指定列名。


选项 2

tshauck 的方法最终比选项 1 更好,因为可以指定列。但是,根据引用列的方式,还有其他变化:

例如,使用数据框中的位置

df_new = df[df[df.columns[2]] != 0]

或者通过如下方式明确指示列

df_new = df[df['line_race'] != 0]

也可以使用相同的登录名,但使用自定义 lambda 函数,例如

df_new = df[df.apply(lambda x: x['line_race'] != 0, axis=1)]

[Out]:
     line_date  daysago  line_race  rating        rw    wrating
0   2007-03-31       62       11.0      56  1.000000  56.000000
1   2007-03-10       83       11.0      67  1.000000  67.000000
2   2007-02-10      111        9.0      66  1.000000  66.000000
3   2007-01-13      139       10.0      83  0.880678  73.096278
4   2006-12-23      160       10.0      88  0.793033  69.786942
5   2006-11-09      204        9.0      52  0.636655  33.106077
6   2006-10-22      222        8.0      66  0.581946  38.408408
7   2006-09-29      245        9.0      70  0.518825  36.317752
8   2006-09-16      258       11.0      68  0.486226  33.063381
9   2006-08-30      275        8.0      72  0.446667  32.160051
10  2006-02-11      475        5.0      65  0.164591  10.698423

选项 3

使用pandas.Series.map自定义 lambda 函数

df_new = df['line_race'].map(lambda x: x != 0)

[Out]:
     line_date  daysago  line_race  rating        rw    wrating
0   2007-03-31       62       11.0      56  1.000000  56.000000
1   2007-03-10       83       11.0      67  1.000000  67.000000
2   2007-02-10      111        9.0      66  1.000000  66.000000
3   2007-01-13      139       10.0      83  0.880678  73.096278
4   2006-12-23      160       10.0      88  0.793033  69.786942
5   2006-11-09      204        9.0      52  0.636655  33.106077
6   2006-10-22      222        8.0      66  0.581946  38.408408
7   2006-09-29      245        9.0      70  0.518825  36.317752
8   2006-09-16      258       11.0      68  0.486226  33.063381
9   2006-08-30      275        8.0      72  0.446667  32.160051
10  2006-02-11      475        5.0      65  0.164591  10.698423

选项 4

使用pandas.DataFrame.drop如下

df_new = df.drop(df[df['line_race'] == 0].index)

[Out]:
     line_date  daysago  line_race  rating        rw    wrating
0   2007-03-31       62       11.0      56  1.000000  56.000000
1   2007-03-10       83       11.0      67  1.000000  67.000000
2   2007-02-10      111        9.0      66  1.000000  66.000000
3   2007-01-13      139       10.0      83  0.880678  73.096278
4   2006-12-23      160       10.0      88  0.793033  69.786942
5   2006-11-09      204        9.0      52  0.636655  33.106077
6   2006-10-22      222        8.0      66  0.581946  38.408408
7   2006-09-29      245        9.0      70  0.518825  36.317752
8   2006-09-16      258       11.0      68  0.486226  33.063381
9   2006-08-30      275        8.0      72  0.446667  32.160051
10  2006-02-11      475        5.0      65  0.164591  10.698423

选项 5

使用pandas.DataFrame.query如下

df_new = df.query('line_race != 0')

[Out]:
     line_date  daysago  line_race  rating        rw    wrating
0   2007-03-31       62       11.0      56  1.000000  56.000000
1   2007-03-10       83       11.0      67  1.000000  67.000000
2   2007-02-10      111        9.0      66  1.000000  66.000000
3   2007-01-13      139       10.0      83  0.880678  73.096278
4   2006-12-23      160       10.0      88  0.793033  69.786942
5   2006-11-09      204        9.0      52  0.636655  33.106077
6   2006-10-22      222        8.0      66  0.581946  38.408408
7   2006-09-29      245        9.0      70  0.518825  36.317752
8   2006-09-16      258       11.0      68  0.486226  33.063381
9   2006-08-30      275        8.0      72  0.446667  32.160051
10  2006-02-11      475        5.0      65  0.164591  10.698423

选项 6

使用pandas.DataFrame.dropandpandas.DataFrame.query如下

df_new = df.drop(df.query('line_race == 0').index)

[Out]:
     line_date  daysago  line_race  rating        rw    wrating
0   2007-03-31       62       11.0      56  1.000000  56.000000
1   2007-03-10       83       11.0      67  1.000000  67.000000
2   2007-02-10      111        9.0      66  1.000000  66.000000
3   2007-01-13      139       10.0      83  0.880678  73.096278
4   2006-12-23      160       10.0      88  0.793033  69.786942
5   2006-11-09      204        9.0      52  0.636655  33.106077
6   2006-10-22      222        8.0      66  0.581946  38.408408
7   2006-09-29      245        9.0      70  0.518825  36.317752
8   2006-09-16      258       11.0      68  0.486226  33.063381
9   2006-08-30      275        8.0      72  0.446667  32.160051
10  2006-02-11      475        5.0      65  0.164591  10.698423

选项 7

如果对输出没有强烈的意见,可以使用矢量化方法numpy.select

df_new = np.select([df != 0], [df], default=np.nan)

[Out]:
[['2007-03-31' 62 11.0 56 1.0 56.0]
 ['2007-03-10' 83 11.0 67 1.0 67.0]
 ['2007-02-10' 111 9.0 66 1.0 66.0]
 ['2007-01-13' 139 10.0 83 0.880678 73.096278]
 ['2006-12-23' 160 10.0 88 0.793033 69.786942]
 ['2006-11-09' 204 9.0 52 0.636655 33.106077]
 ['2006-10-22' 222 8.0 66 0.581946 38.408408]
 ['2006-09-29' 245 9.0 70 0.518825 36.317752]
 ['2006-09-16' 258 11.0 68 0.486226 33.063381]
 ['2006-08-30' 275 8.0 72 0.446667 32.160051]
 ['2006-02-11' 475 5.0 65 0.164591 10.698423]]

这也可以使用以下方式转换为数据框:

df_new = pd.DataFrame(df_new, columns=df.columns)

[Out]:
     line_date daysago line_race rating        rw    wrating
0   2007-03-31      62      11.0     56       1.0       56.0
1   2007-03-10      83      11.0     67       1.0       67.0
2   2007-02-10     111       9.0     66       1.0       66.0
3   2007-01-13     139      10.0     83  0.880678  73.096278
4   2006-12-23     160      10.0     88  0.793033  69.786942
5   2006-11-09     204       9.0     52  0.636655  33.106077
6   2006-10-22     222       8.0     66  0.581946  38.408408
7   2006-09-29     245       9.0     70  0.518825  36.317752
8   2006-09-16     258      11.0     68  0.486226  33.063381
9   2006-08-30     275       8.0     72  0.446667  32.160051
10  2006-02-11     475       5.0     65  0.164591  10.698423

至于最有效的解决方案,这取决于人们如何衡量效率。假设人们想要测量执行时间,一种方法是使用time.perf_counter()

如果测量上述所有选项的执行时间,可以得到以下结果

       method                   time
0    Option 1 0.00000110000837594271
1  Option 2.1 0.00000139995245262980
2  Option 2.2 0.00000369996996596456
3  Option 2.3 0.00000160001218318939
4    Option 3 0.00000110000837594271
5    Option 4 0.00000120000913739204
6    Option 5 0.00000140001066029072
7    Option 6 0.00000159995397552848
8    Option 7 0.00000150001142174006

在此处输入图片描述

但是,这可能会根据所使用的数据框、要求(例如硬件)等而改变。


笔记:

  • 关于使用有各种建议inplace=True。建议阅读此文:https ://stackoverflow.com/a/59242208/7109869

  • 还有一些人对此有强烈的意见.apply()。建议阅读此文:我什么时候应该(不)想在代码中使用 pandas apply()?

  • 如果有缺失值,可能还需要考虑pandas.DataFrame.dropna。使用选项 2,它将类似于

df = df[df['line_race'] != 0].dropna()
  • 还有其他方法可以测量执行时间,因此我推荐这个线程: 如何获取 Python 程序执行的时间?

解决方案 10:

其中一种有效且流行的方法是使用eq()方法:

df[~df.line_race.eq(0)]

解决方案 11:

另一种方法。可能不是最有效的方法,因为代码看起来比其他答案中提到的代码更复杂一些,但仍然是做同样事情的另一种方法。

  df = df.drop(df[df['line_race']==0].index)

解决方案 12:

我编译并运行了我的代码。这是准确的代码。你可以自己尝试一下。

data = pd.read_excel('file.xlsx')

''如果列名中有任何特殊字符或空格,您可以像给定的代码中那样写入:

data = data[data['expire/t'].notnull()]
print (date)

如果只有一个字符串列名,没有任何空格或特殊字符,则可以直接访问它。

data = data[data.expire ! = 0]
print (date)

解决方案 13:

提供了这么多选项(或者也许我没有太注意,如果是这种情况,很抱歉),但没有人提到这一点:我们可以在 pandas 中使用这种符号:〜(这给了我们条件的逆)

df = df[~df["line_race"] == 0]

解决方案 14:

只需添加另一种方法即可扩展所有列的 DataFrame:

for column in df.columns:
   df = df[df[column]!=0]

例子:

def z_score(data,count):
   threshold=3
   for column in data.columns:
       mean = np.mean(data[column])
       std = np.std(data[column])
       for i in data[column]:
           zscore = (i-mean)/std
           if(np.abs(zscore)>threshold):
               count=count+1
               data = data[data[column]!=i]
   return data,count

解决方案 15:

以防万一您需要删除行,但值可能位于不同的列中。在我的例子中,我使用的是百分比,所以我想删除任何列中值为 1 的行,因为这意味着它是 100%

for x in df:
    df.drop(df.loc[df[x]==1].index, inplace=True)

如果你的 df 有太多列,则不是最佳选择。

解决方案 16:

您可以尝试使用这个:

df.drop(df[df.line_race != 0].index, inplace = True)

解决方案 17:

如果需要根据索引值删除行,则顶部答案中的布尔索引也可以调整。例如,在下面的代码中,索引在 3 到 7 之间的行将被删除。

df = pd.DataFrame({'A': range(10), 'B': range(50,60)})

x = df[(df.index < 3) | (df.index > 7)]
# or equivalently
y = df[~((df.index >= 3) & (df.index <= 7))]

# or using query
z = df.query("~(3 <= index <= 7)")


# if the index has a name (as in the OP), use the name
# to select rows in 2007:
df.query("line_date.dt.year == 2007")

正如其他人提到的,query()这是一个非常易读的函数,非常适合这项任务。事实上,对于大型数据帧,它是完成这项任务的最快方法(请参阅此答案以了解基准测试结果)。

一些常见问题query()

  1. 对于带有空格的列名,请使用反引号。

df = pd.DataFrame({'col A': [0, 1, 2, 0], 'col B': ['a', 'b', 'cd', 'e']})

# wrap a column name with space by backticks
x = df.query('`col A` != 0')
  1. 要引用本地环境中的变量,请在其前面加上@

to_exclude = [0, 2]
y = df.query('`col A` != @to_exclude')
  1. 也可以调用系列方法。

# remove rows where the length of the string in column B is not 1
z = df.query("`col B`.str.len() == 1")

解决方案 18:

对于像这样的简单示例,这并没有太大区别,但对于复杂的逻辑,我更喜欢drop()在删除行时使用,因为它比使用逆逻辑更直接。例如,删除行A=1 AND (B=2 OR C=3)

这是一个易于理解且可以处理复杂逻辑的可扩展语法:

df.drop( df.query(" `line_race` == 0 ").index)

解决方案 19:

此主题中有几个答案涉及索引,如果索引有重复项,大多数答案都将不起作用。是的,上面的至少一条评论已经指出了这一点,并且还指出重新索引是解决此问题的一种方法。下面是一个带有重复索引的示例来说明该问题。

df = pd.DataFrame(data=[(1,'A'), (0,'B'), (1,'C')], index=[1,2,2],
                  columns=['line_race','C2'])
print("Original with a duplicate index entry:")
print(df)

df = pd.DataFrame(data=[(1,'A'), (0,'B'), (1,'C')], index=[1,2,2],
                  columns=['line_race','C2'])
df.drop(df[df.line_race == 0].index, inplace = True)
print("
Incorrect rows removed:")
print(df)

df = pd.DataFrame(data=[(1,'A'), (0,'B'), (1,'C')], index=[1,2,2],
                  columns=['line_race','C2'])
df.reset_index(drop=False, inplace=True)
df.drop(df[df.line_race == 0].index, inplace = True)
df.set_index('index', drop=True, inplace=True)
df.index.name = None
print("
Correct row removed:")
print(df)

这是输出:

Original with a duplicate index entry:
   line_race C2
1          1  A
2          0  B
2          1  C

Incorrect rows removed:
   line_race C2
1          1  A

Correct row removed:
   line_race C2
1          1  A
2          1  C

解决方案 20:

使用.loc而不使用.drop,您可以使用:

df = df.loc[df['line_race']!=0]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用