使用 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']
已解释
re.sub
函数替换给定的字符串(此处:item
),例如
搜索和替换。
- search 由正则表达式指定:
\W
所有非单词字符(即非数字、非字母
字母)。
- 将replace指定为一个空字符串来简单
删除找到的:
''
.
- 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)
,因此过滤。
另见
- 官方 Python 3 文档:re — Regular expression operations
- 官方 Python 3 文档:Regular Expression HOWTO
- 类似的 SO 答案:Filtering text in python for numeric values
- 关于 原始字符串 的有趣问题:Python regex - r prefix
我有一个数据集,其中包含带有字母数字值的列。我现在可以过滤不匹配的记录,我想清理它们,这意味着例如不匹配的记录是 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']
已解释
re.sub
函数替换给定的字符串(此处:item
),例如 搜索和替换。- search 由正则表达式指定:
\W
所有非单词字符(即非数字、非字母 字母)。 - 将replace指定为一个空字符串来简单
删除找到的:
''
. - 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)
,因此过滤。
另见
- 官方 Python 3 文档:re — Regular expression operations
- 官方 Python 3 文档:Regular Expression HOWTO
- 类似的 SO 答案:Filtering text in python for numeric values
- 关于 原始字符串 的有趣问题:Python regex - r prefix