在python中使用正则表达式查找特定的数字模式

时间:2020-10-20 00:56:54

标签: python regex dataframe

我想替换以“ -99”开头的数据框列中的所有值。与NaN一起使用正则表达式,因为它们是异常值。

我使用了df['Item'].replace(r(^[-][9][9]\d.*$),np.NaN),但是没有用。

2 个答案:

答案 0 :(得分:1)

TL; DR

etag发布的正则表达式可以很好地检测以@tripleee开头的数字(编码为字符串),这里的问题是您正在处理数字,而正则表达式仅适用于字符串。

MCVE

让我们建立一个综合的例子:

-99.

正则表达式

然后,您可以使用正则表达式match离群值(只要字符串格式适合),那么您所需要的就是在应用正则表达式(位于astype系列工具)。

import numpy as np
import pandas as pd

df = pd.DataFrame([-999, -99.9, -9, 9, 99.9, 0., 1, -999], columns=['Item'])

    Item
0 -999.0
1  -99.9
2   -9.0
3    9.0
4   99.9
5    0.0
6    1.0
7 -999.0

但是,如果您打算使用字符串对象的replace函数将这些值替换为q1 = df['Item'].astype(str).str.match(r'^-99\..*') 0 False 1 True 2 False 3 False 4 False 5 False 6 False 7 False ,则将需要额外的步骤,因为此str函数期望使用另一个字符串,而无需使用其他字符串(使用{{1} }或nan将失败)。然后,您将必须执行:

np.nan

IMO这是一个非常糟糕的单行代码,因为“不必要的”转换会破坏数据的本质。

逻辑索引

您最好使用上面的布尔向量选择replace,方法是替换为哨兵:

None

或切片:

df['Item'].astype(str).str.replace(r'^-99\..*', 'nan').astype(float)

无论如何将数字转换为字符串以检测异常值似乎都有些奇怪(性能差,难以调试的复杂行为,多余的数据副本)。

浮点运算

简单过滤器

如果没有理由认为少于df.loc[q1] = np.nan Item 0 -999.0 1 NaN 2 -9.0 3 9.0 4 99.9 5 0.0 6 1.0 7 -999.0 的数字仍然有效,则可以使用简单的数字条件将其过滤掉:

df = df.loc[~q1,:]

    Item
0 -999.0
2   -9.0
3    9.0
4   99.9
5    0.0
6    1.0
7 -999.0

哪种方式会更好,并且避免将数字强制转换为字符串,反之亦然。它还避免了额外的数据副本(字符串,然后再次浮动,然后覆盖初始数据)。因此,就您的首选而言,这将同时具有内存(数据副本)和计算(正则表达式密集)的效率。

Epsilon球滤器

如果必须保留小于截止值的数字,则仍可以使用浮点运算来执行它。只需将ε球准则的小于准则更改为所需的值即可。要捕获-99.中的所有数字,您可以使用以下设置:

q2 = df['Item'] <= -99.
df = df.loc[~q2,:]

   Item
2  -9.0
3   9.0
4  99.9
5   0.0
6   1.0

当然,您可以更改[-100., -99.],并根据机器的精度将target = -99.5 epsilon = 0.5 q3 = np.abs(df['Item'] - target) <= epsilon 0 False 1 True 2 False 3 False 4 False 5 False 6 False 7 False 设置得尽可能小。

答案 1 :(得分:0)

不知道有关Pandas的信息,但是您显示的代码缺少引号,当然,正则表达式不会执行您想执行的操作。 \d*.$说必须 结尾,后跟数字和任意字符。也许你是说

df['Item'].replace(r'^-99\..*',np.NaN)

其中^锚表示行的开头(或此处的单元格的开头),而-99仅匹配文字文本。最终\.匹配一个文字点,.*之后匹配所有内容,直到单元格的末尾。