【问题标题】:Replace String Value Digits based on their count in python?根据python中的计数替换字符串值数字?
【发布时间】:2020-10-23 15:27:29
【问题描述】:
df:
    Col_A        Month
0 March 2020      Mar
1 March 20        Mar
2 Ebg 2020        Mar
3 17 GOFE         Mar
4 APR 17          Mar
5 16 HGN          Nov
6 2015 ref        May
7 18Jun           Jul

如何从 Pandas 数据框中的字符串变量中替换数字, 例如,我需要将 Col_A 中的数字替换为 2019 或 19。 如果 col_A 中的位数或长度为 4,则为 2019,否则为 19。

输出:

    Col_A        Month
0 March 2019      Mar
1 March 19        Mar
2 Ebg 2019        Mar
3 19 GOFE         Mar
4 APR 19          Mar
5 19 HGN          Nov
6 2019 ref        May
7 19Jun           Jul

【问题讨论】:

    标签: python python-3.x regex pandas


    【解决方案1】:

    由于问题中的示例包含两个和四个字符串的字符串,我假设四位字符串的最后两位将替换为"19",两位数的字符串将替换为"19" .

    以下正则表达式可以与re.sub 一起使用来进行这些替换。

    r'(?<!\d)(?=\d{2}(?!\d))\d{2}|(?<=(?<!\d)\d{2})\d{2}(?!\d)'
    

    字符串:

    1 2 GOFE          Mar
    2 23 GOFE         Mar
    3 567 GOFE        Mar
    4 5678 GOFE       Mar
    5 3456789 GOFE    Mar
    

    分别变成:

    1 2 GOFE          Mar
    2 19 GOFE         Mar
    3 567 GOFE        Mar
    4 5619 GOFE       Mar
    5 34567 GOFE      Mar
    

    regex demo|Python demo

    Python 的正则表达式引擎执行以下操作。

    (?<!\d)   : use negative lookbehind to assert previous
                character is not a digit
    (?=       : begin positive lookahead
      \d{2}   : match 2 digits
      (?!\d)  : use negative lookahead to assert next
                character is not a digit 
    )         : end non-capture group
    \d{2}     : match 2 digits
    |         : or
    (?<=      : begin positive lookbehind
      (?<!\d) : use negative lookbehind to assert previous
                character is not a digit
      \d{2}   : match 2 digits
    )         : end positive lookbehind
    \d{2}     : match 2 digits
    (?!\d)    : use negative lookahead to assert next
                character is not a digit 
    

    【讨论】:

      【解决方案2】:

      这里是你如何使用re

      import pandas as pd
      from re import sub, findall
      
      df = pd.DataFrame(...)
      df['Col_A'] = [sub('\d\d\d\d','2019',m)
                     if findall('\d\d\d\d',m)
                     else sub('\d\d','19',m)
                     for m in df['Col_A']]
      

      更新:另一种方式:

      import pandas as pd
      from re import sub, findall
      
      df = pd.DataFrame(...)
      
      df['Col_A'] = df.Col_A.map(lambda m: sub('[0-9]{4}','2019',m)
                                 if findall('[0-9]{4}',m)
                                 else sub('[0-9]{2}','19',m))
      


      更新:cs95 给出了这个简短的解决方案:

      import pandas as pd
      
      df = pd.DataFrame(...)
      
      df['Col_A'] = df['Col_A'].str.replace('\d{2}(?!\d)', '19')
      

      【讨论】:

      • 这看起来很丑,你能做得更好吗?通常我们不喜欢迭代 DataFrames,如果你想在 pandas 上取得成功,你需要学习矢量化例程。不是反对者。
      • 此外,您正在评估多达三个不同的正则表达式(这有点低效)以实现 Cary Swoveland 在一个中所做的。
      • 更好,但仍有改进的余地。 Pandas 支持带有字符串函数的正则表达式:df['Col_A'].str.replace('\d{2}(?!\d)', '19') 是我的做法。罗马不是一天建成的,我建议在写自己之前观察标签中的其他答案。
      猜你喜欢
      • 2021-12-05
      • 2012-03-17
      • 1970-01-01
      • 1970-01-01
      • 2013-06-11
      • 2021-06-19
      • 2014-05-07
      • 2022-01-03
      • 1970-01-01
      相关资源
      最近更新 更多