【问题标题】:Rename columns with regex and Pandas to extract contents between specific punctuations使用正则表达式和 Pandas 重命名列以提取特定标点符号之间的内容
【发布时间】:2021-04-02 15:08:24
【问题描述】:

给定一个测试数据集如下:

  city district  ... Q3:*your age[open question]  Q4:*skill[open question]
0   bj       cy  ...                          45                              R
1   bj       cy  ...                          34                         Python

我需要使用正则表达式重命名列,以提取*[ 之间的内容,如果存在your,还要删除它们。请注意,在实际情况下,我有很多问题列如下。

df.columns
Out[112]: 
Index(['city', 'district', 'name', 'Q1:*your tel[open question]',
       'Q2:*your profession[close question]', 'Q3:*your age[open question]',
       'Q4:*skill[open question]'],
      dtype='object')

预期的列将如下所示:

['city', 'district', 'name', 'tel', 'profession', 'age', 'skill']

如何在 Pandas 和正则表达式中做到这一点?非常感谢。

【问题讨论】:

    标签: python-3.x regex pandas dataframe


    【解决方案1】:
    df13 = df.filter(regex = '^[^Q]', axis = 1) #Isolate columns without Q
    df12 = df.filter(regex = '^Q', axis = 1) #isolate columns with Q
    x = df.filter(regex = '^Q', axis = 1).reindex(df.filter(regex = '^Q', axis = 1).\
    columns.str.findall('([a-z]+(?=\[))').str.join(','),\
    axis = "columns").columns # transform column names with q
    df12.columns=list(x) # reset df12 column names
    pd.concat([df13, df12], axis = 1)
    

    示例数据

    df=pd.DataFrame({'city':[1], 'district':[1], 'name':[1], 'Q1:*your tel[open question]':[1],
           'Q2:*your profession[close question]':[1], 'Q3:*your age[open question]':[1],
           'Q4:*skill[open question]':[1]})
    

    打印(df)

     city  district  name  Q1:*your tel[open question]  \
    0     1         1     1                            1   
    
       Q2:*your profession[close question]  Q3:*your age[open question]  \
    0                                    1                            1   
    
       Q4:*skill[open question]  
    0                         1  
    

    结果

        city  district  name  tel  profession  age  skill
    0     1         1     1    1           1    1      1
    

    【讨论】:

      【解决方案2】:

      每当遇到这样的问题时,您可能想给自己一些时间来思考哪种模式与您想要的匹配。为此,我推荐this site,您可以在其中粘贴目标文本并尝试一些模式。这需要一些时间,但这就是我们实际学习的方式(正则表达式对大脑来说总是一种很好的锻炼)。

      对于您的情况,您想要的模式是r'\*(your)?(.*)\[',其中第二个匹配组是要成为列新名称的单词。所以你可以试试这样的:

      import re
      
      pattern = r'\*(your)?(.*)\['
      
      print('# Before\n', df.columns)
      df = df.rename({
           col: re.search(pattern, col).group(2).strip() 
           if re.search(pattern, col) 
           else col 
           for col in df.columns
           }, axis=1)
      print('# After\n', df.columns)
      

      输出将是:

      # Before
       Index(['city', 'district', 'name', 'Q1:*your tel[open question]',
             'Q2:*your profession[close question]', 'Q3:*your age[open question]',
             'Q4:*skill[open question]'],
            dtype='object')
      # After
       Index(['city', 'district', 'name', 'tel', 'profession', 'age', 'skill'], dtype='object')
      

      【讨论】:

      • 谢谢,regex101.com 也很有帮助。
      • 我想您已经使用了两种模式,能否请您将它们发布在代码部分以便我进行测试?
      • 对不起,只有一种模式,但我忘了将它添加到答案中。我马上修改
      • 我不明白,对于这种模式,对于内部没有yourQ4:*skill[open question] 是如何工作的?
      • 它在(your) 之后有一个?,这意味着它将匹配0 或1 次出现的your。试一试,你会看到它的工作原理
      【解决方案3】:

      试试:

      cols = []
      for i in df.columns:
          if re.search(r'Q\d:',i) != None:
              cols.append(re.match(r'^Q\d:\*(your\s)?([\w]*)',i).group(2))
          else:
              cols.append(i)
      

      上面的 Oneliner 替代品:

      [(re.match(r'^Q\d:\*(your\s)?([\w]*)',i).group(2)) if re.search(r'Q\d:',i) is not None else i for i in df.columns]
      

      两个打印件:

      ['city', 'district', 'name', 'tel', 'profession', 'age', 'skill']
      

      【讨论】:

      • 谢谢,group(2) 在您的代码中代表什么?
      • 哦,该正则表达式模式中有两个捕获组,一个用于可选(your\s)?,另一个用于您想要作为列名([\w]*) 的实际字符串。所以我使用group(2) 来捕获第二个捕获组值。
      • 刚刚注意到@ralubrusto 在他的回答col: re.search(pattern, col).group(2).strip()中也使用了类似的东西@
      • 是的,我用if re.search(r'Q\d:',i) != None: print(cols) 尝试我的真实数据,但它返回多个空列表。我不明白为什么会这样。 @ralubrusto 的解决方案没有这个错误。
      猜你喜欢
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      • 2020-11-16
      • 2020-09-27
      • 2018-05-23
      • 1970-01-01
      • 2019-01-07
      • 2020-01-07
      相关资源
      最近更新 更多