【问题标题】:Best way to clean up the unmatched records given by REGEX (Alphanumeric) using python?使用python清理REGEX(字母数字)给出的不匹配记录的最佳方法?
【发布时间】:2021-06-21 13:27:51
【问题描述】:

我有一个数据集,其中有包含字母数字值的列。我现在可以过滤不匹配的记录,我想清理它们,这意味着例如不匹配的记录是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

【问题讨论】:

    标签: python regex dataframe re alphanumeric


    【解决方案1】:

    使用内置 Regex 模块 re 的普通 Python 即可。 看到这个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. 搜索由正则表达式指定: \W 所有非单词字符(即非数字、非字母 字母)。
    3. replace 由一个空字符串指定,以简单地 删除找到的:''
    4. for-loop 实现为 list-comprehension, 一种用于迭代 a 元素的意识形态或 pythonic 方式 列表。

    过滤以上部分

    如果您想仅过滤部分,例如仅字母或仅数字字符,那么您需要像 demo on IDEone 中那样组合 PCRE 的 元字符

    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'] 字母数字 ['abc123', 'abc123', 'Abc123', 'ABC123', '123Abc', '123abc', '123abc'] 数字 ['123', '123', '123', '123', '123', '123', '123'] 阿尔法 ['abc', 'abc', 'Abc', 'ABC', 'Abc', 'abc', 'abc']

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

    另见

    【讨论】:

    • 毫无疑问。同样的场景,我们如何去除整数
    • @Pysdm @Pysdm 没有标点符号,我将其理解为“修辞”问题。 ? 整数可以通过替换 digits \d+ 的正则表达式或相反的方法来同样删除:使用匹配的PCRE metachar 使用正则表达式搜索any non-digits 进行过滤(类似于\w匹配word-chars否定\W..所以\d变成❔)。
    • 抱歉,这是一个数字,但是当我尝试同时删除整数和特殊字符时,它不起作用。当我只给 r'\d+' 时,它正在删除整数并删除字母 r'[a-zA-Z]+' 但是当我想删除 int,spcl char 时,它不会删除。我给了一个模式 r'[$&+,:;=?@#|.^*()%!-][\d+]' 它正在删除
    • 我明白了。 ([^\d]+?)' 用于删除整数和 ([^a-zA-z]+?)' 用于字母
    • @Pysdm 你明白了?️ 更简单,没有括号/捕获组(),否定运算符^ 或贪婪-quantifier?。例如只保留特殊字符可以被re.sub('[A-Za-z\d]', '', s)变成“删除digits and alphas”。
    猜你喜欢
    • 2023-02-13
    • 2019-06-05
    • 1970-01-01
    • 2021-01-21
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多