正则表达式在多个模式之前找到一个数字序列,放入一个新列(Python,Pandas)

Posted

技术标签:

【中文标题】正则表达式在多个模式之前找到一个数字序列,放入一个新列(Python,Pandas)【英文标题】:Regular expression to find a sequence of numbers before multiple patterns, into a new column (Python, Pandas) 【发布时间】:2021-01-17 20:39:45 【问题描述】:

这是我的样本数据

import pandas as pd
import re
  
cars = pd.DataFrame('Engine Information': 0: 'Honda 2.4L 4 cylinder 190 hp 162 ft-lbs',
          1: 'Aston Martin 4.7L 8 cylinder 420 hp 346 ft-lbs',
          2: 'Dodge 5.7L 8 Cylinder 390hp 407 ft-lbs',
          3: 'MINI 1.6L 4 Cylinder 118 hp 114 ft-lbs',
          4: 'Ford 5.0L 8 Cylinder 360hp 380 ft-lbs FFV',
          5: 'GMC 6.0L 8 Cylinder 352 hp 382 ft-lbs',
         'HP': 0: None, 1: None, 2: None, 3: None, 4: None, 5: None)

这是我的想要的输出

我创建了一个名为“HP”的新列,我想从原始列(“引擎信息”)中提取马力数据

这是我尝试执行此操作的代码

cars['HP'] = cars['Engine Information'].apply(lambda x: re.match(r'\\d+(?=\\shp|hp)', str(x)))

这个想法是我想用正则表达式匹配模式:'在'hp'或'hp'之前出现的数字序列。这是因为某些单元格在数字和“hp”之间没有“空格”,如我的示例所示。

我确定正则表达式是正确的,因为我已经在 R 中成功完成了类似的过程。但是,我尝试了诸如 str.extractre.findallre.searchre.match 之类的函数。返回错误或“无”值(如示例中所示)。所以在这里我有点失落。

谢谢!

【问题讨论】:

为什么“s”前面有两个“\”? \d+(?=\\shp|hp)。删除一个时,它会正确匹配所有 hp 值:regex101.com/r/Aeh0LX/1 r'\\d+(?=\\shp|hp)' ==> r'\d+(?=\shp|hp)''\\d+(?=\\shp|hp)' 尝试了这两种解决方案,仍然在我的表中返回“无”值。 【参考方案1】:

你可以使用str.extract:

cars['HP'] = cars['Engine Information'].str.extract(r'(\d+)\s*hp\b', flags=re.I)

详情

(\d+)\s*hp\b - 匹配并捕获到第 1 组一个或多个数字,然后仅匹配 0 个或多个空格 (\s*) 和 hp(由于 flags=re.I 不区分大小写)作为一个完整的单词(因为 @ 987654329@ 标记一个单词边界) str.extract 仅在模式中有捕获组时才返回捕获的值,因此 hp 和空格不是结果的一部分。

Python 演示结果:

>>> cars
                               Engine Information   HP
0         Honda 2.4L 4 cylinder 190 hp 162 ft-lbs  190
1  Aston Martin 4.7L 8 cylinder 420 hp 346 ft-lbs  420
2          Dodge 5.7L 8 Cylinder 390hp 407 ft-lbs  390
3          MINI 1.6L 4 Cylinder 118 hp 114 ft-lbs  118
4       Ford 5.0L 8 Cylinder 360hp 380 ft-lbs FFV  360
5           GMC 6.0L 8 Cylinder 352 hp 382 ft-lbs  352

【讨论】:

另见this Python demo online。 起初这返回了我:TypeError: extract() got an unexpected keyword argument 'expand',但是我删除了“提取”参数并且它运行良好。 @k3b 奇怪,请参阅文档:“expand : bool, default True If True,每个捕获组返回一列 DataFrame。如果为 False,如果有一个捕获组,则返回 Series/Index;如果有多个捕获组,则返回 DataFrame。"【参考方案2】:

有几个问题:

re.match 只查看字符串的开头,如果您的模式可能出现在任何地方,请使用 re.search 如果您使用原始字符串,请不要转义,即'\\d hp'r'\d hp' - 原始字符串可以帮助您避免转义 返回匹配组。您只是搜索但不产生找到的组。 re.search(rex, string) 为您提供一个复杂对象(匹配对象),您可以从中提取所有组,例如re.search(rex, string)[0] 您必须将访问封装在一个单独的函数中,因为您必须在访问组之前检查是否有任何匹配项。如果您不这样做,异常可能会在中间停止应用过程 应用速度慢;使用 pandas 矢量化函数,例如提取:cars['Engine Information'].str.extract(r'(\d+) ?hp')

你的方法应该适用于这个:

def match_horsepower(s):
    m = re.search(r'(\d+) ?hp', s)
    return int(m[1]) if m else None

cars['HP'] = cars['Engine Information'].apply(match_horsepower)

【讨论】:

【参考方案3】:

这将在 hp 之前获得数值,不带或带(单个或多个)空格。

r'\d+(?=\s+hp|hp)'

您可以在此处验证正则表达式:https://regex101.com/r/pXySxm/1

【讨论】:

感谢您的回答,但我仍然收到“无”值返回。

以上是关于正则表达式在多个模式之前找到一个数字序列,放入一个新列(Python,Pandas)的主要内容,如果未能解决你的问题,请参考以下文章

使用正则表达式匹配多个逗号分隔的单词

只有在字符串中找到一组数字时,C# 正则表达式才匹配

正则表达式模式单个和多个相同字符的实例

正则表达式怎么匹配前面紧跟某个字符串的字符

perl正则表达式

Notepad++正则表达式