使用 python 清理 REGEX(字母数字)给出的不匹配记录的最佳方法?

Best way to clean up the unmatched records given by REGEX (Alphanumeric) using python?

我有一个数据集,其中包含带有字母数字值的列。我现在可以过滤不匹配的记录,我想清理它们,这意味着例如不匹配的记录是 123*abc& 那么它应该删除 123abc。我已经做到了,但我认为这不是正确的方法,而且数据是在最终结果之后合并的,我可以使用 for 循环来正确获取它们,但这将是一个缓慢的过程。因此寻找更简单的方法(逐列清理)。可以这样做吗?

data = ['abc123','abc*123&','Abc123','ABC@*&123',np.nan,'123*Abc']
df=pd.DataFrame(data, columns=['a'])
print(df)
       a
0     abc123
1   abc*123&
2     Abc123
3  ABC@*&123
4        NaN
5    123*Abc

正在过滤不匹配的记录:

wrong=df[~df['a'].str.contains(numeric, na=True)]
print(wrong)
        a
1   abc*123&
3  ABC@*&123
5    123*Abc


wrong_index = wrong.index
result = ''.join(i for i in wrong['a'] if not i.isalpha())  
alphanumeric = [character for character in result if character.isalnum()]
alphanumeric = "".join(alphanumeric)
df['a'].loc[wrong_index]=alphanumeric
print(df)
     a
0   abc123
1   abc123ABC123123Abc
2   Abc123
3   abc123ABC123123Abc
4   NaN
5   abc123ABC123123Abc

我知道为什么会这样,可以通过使用 for 或循环遍历每一行来解决,但它会消耗大量时间。有什么办法可以逐列清理吗?

异常输出:

       a
0     abc123
1     abc123
2     Abc123
3     ABC123
4        NaN
5     123Abc

使用普通的 vanilla Python 使用内置的 Regex 模块 re 就可以了。 看到这个 demo on IDEone: using regular-expression to replace list elements

import re

data = ['abc123','abc*123&','Abc123','ABC@*&123','123*Abc']
cleaned = [re.sub('\W', '', item) for item in data]
print(cleaned)

脚本将输出:

['abc123', 'abc123', 'Abc123', 'ABC123', '123Abc']

已解释

  1. re.sub 函数替换给定的字符串(此处:item),例如 搜索和替换。
  2. search 由正则表达式指定: \W 所有非单词字符(即非数字、非字母 字母)。
  3. replace指定为一个空字符串来简单 删除找到的:''.
  4. for-loop实现为 list-comprehension, 一种思想或 pythonic 的方式来迭代 a 的元素 列表。

筛选以上部分

如果你想只过滤部分,比如只过滤字母或数字字符,那么你需要组合 PCRE 的 元字符 就像这样 demo on IDEone:

import re

data = ['abc123','abc*123&','Abc123','ABC@*&123','123*Abc', '123_abc', '123 abc']

# replace non-alphas and non-digits; filter [A-Za-z0-9_]
alphanumeric_underscore = [re.sub('\W', '', item) for item in data]
print('alphanumeric_underscore', alphanumeric_underscore)

# replace also the underscore; filter [A-Za-z0-9]
alphanumeric = [re.sub('[\W_]', '', item) for item in data]
print('alphanumeric', alphanumeric)

# filter only digits
numeric = [re.search(r"\d+", item).group(0) for item in data]
print('numeric', numeric)

# filter only alphas
alpha = [re.search(r"[A-Za-z]+", item).group(0) for item in data]
print('alpha', alpha)

它将输出:

alphanumeric_underscore ['abc123', 'abc123', 'Abc123', 'ABC123', '123Abc', '123_abc', '123abc'] alphanumeric ['abc123', 'abc123', 'Abc123', 'ABC123', '123Abc', '123abc', '123abc'] numeric ['123', '123', '123', '123', '123', '123', '123'] alpha ['abc', 'abc', 'Abc', 'ABC', 'Abc', 'abc', 'abc']

它使用正则表达式搜索 re.search 和正则表达式(前缀为原始字符串)r"\d+" 到 return 所有找到的事件 .group(0),因此过滤。

另见