我想替换以“ -99”开头的数据框列中的所有值。与NaN
一起使用正则表达式,因为它们是异常值。
我使用了df['Item'].replace(r(^[-][9][9]\d.*$),np.NaN)
,但是没有用。
答案 0 :(得分:1)
由etag
发布的正则表达式可以很好地检测以@tripleee
开头的数字(编码为字符串),这里的问题是您正在处理数字,而正则表达式仅适用于字符串。
让我们建立一个综合的例子:
-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
哪种方式会更好,并且避免将数字强制转换为字符串,反之亦然。它还避免了额外的数据副本(字符串,然后再次浮动,然后覆盖初始数据)。因此,就您的首选而言,这将同时具有内存(数据副本)和计算(正则表达式密集)的效率。
如果必须保留小于截止值的数字,则仍可以使用浮点运算来执行它。只需将ε球准则的小于准则更改为所需的值即可。要捕获-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
仅匹配文字文本。最终\.
匹配一个文字点,.*
之后匹配所有内容,直到单元格的末尾。