使用正则表达式在双倍空格后提取整数

Posted

技术标签:

【中文标题】使用正则表达式在双倍空格后提取整数【英文标题】:Extract integers after double space with regex 【发布时间】:2019-08-06 06:01:35 【问题描述】:

我有一个数据框,我想在双倍空格后提取内容。对于NAME 列中的所有行,在公司名称之后的整数之前有一个双空格。

                                    NAME  INVESTMENT  PERCENT
0     APPLE COMPANY A  57 638 232 stocks     OIL LTD  0.12322
1  BANANA 1 COMPANY B  12 946 201 stocks    GOLD LTD  0.02768
2     ORANGE COMPANY C  8 354 229 stocks     GAS LTD  0.01786

df = pd.DataFrame(
    'NAME': ['APPLE COMPANY A  57 638 232 stocks', 'BANANA 1 COMPANY B  12 946 201 stocks', 'ORANGE COMPANY C  8 354 229 stocks'],
    'PERCENT': [0.12322, 0.02768 , 0.01786]
    )

我之前有这个,但它在公司名称中也包含整数:

df['STOCKS']=df['NAME'].str.findall(r'\b\d+\b').apply(lambda x: ''.join(x))

相反,我尝试在双空格后提取

df['NAME'].str.split('(\s2)')

给出输出:

0       [APPLE COMPANY A,   , 57 638 232 stocks]
1    [BANANA 1 COMPANY B,   , 12 946 201 stocks]
2       [ORANGE COMPANY C,   , 8 354 229 stocks]

但是,我希望将出现在双空格之后的整数连接/合并并放入新列中。

                 NAME  PERCENT  STOCKS
0     APPLE COMPANY A  0.12322  57638232
1  BANANA 1 COMPANY B  0.02768  12946201
2    ORANGE COMPANY C  0.01786  12946201

如何修改我的第二个函数来做我想做的事?

【问题讨论】:

为什么要使用正则表达式?它很慢,您也可以拆分为 2 个空格 (.split(' ')),我假设通过删除您的第一列并创建一个新列,同时将内容放入其中就可以了 【参考方案1】:

遵循您可能使用的原始逻辑

df['STOCKS'] = df['NAME'].str.extract(r'\s2,(\d+(?:\s\d+)*)', expand=False).str.replace(r'\s+', '')
df['NAME'] = df['NAME'].str.replace(r'\s2,\d+(?:\s\d+)*\s+stocks', '')

输出:

                 NAME  PERCENT    STOCKS
0     APPLE COMPANY A  0.12322  57638232
1  BANANA 1 COMPANY B  0.02768  12946201
2    ORANGE COMPANY C  0.01786   8354229

详情

\s2,(\d+(?:\s\d+)*) 用于在 2 个或更多空格之后提取第一次出现的以空格分隔的连续数字块,.replace(r'\s+', '') 之后删除提取文本中的所有空格 .replace(r'\s2,\d+(?:\s\d+)*\s+stocks' 更新 NAME 列中的文本,它删除 2 个或更多空格、连续的空格分隔的数字块,然后是 1+ 空格和 stocks。其实最后一个\s+stocks如果有其他字也可以换成.*

【讨论】:

正则表达式不应该是最好的解决方案,但这很好,所以,为这个 我收到错误消息:'DataFrame' object has no attribute 'str' for df['NAME'].str.extract(r'\s2,(\d+(?:\s\d+)*)').str.replace('\s+', '') @Mataunited17 我使用了您问题中的数据,它适用于我的 Python 3.6。 我明白了。我正在使用 3.7.1。奇怪。 @Mataunited17 添加了expand=False 以便extract 仅返回系列并在Python 3.7 中进行测试。也适用于 Python 3.6。【参考方案2】:

另一种pandas 方法,它将STOCKS 转换为数字类型:

df_split = (df['NAME'].str.extractall('^(?P<NAME>.+)\s2(?P<STOCKS>[\d\s]+)')
            .reset_index(level=1, drop=True))

df_split['STOCKS'] = pd.to_numeric(df_split.STOCKS.str.replace('\D', ''))

将这些列分配回您原来的DataFrame

df[['NAME', 'STOCKS']] = df_split[['NAME', 'STOCKS']]

         COMPANY_NAME    STOCKS  PERCENT
0     APPLE COMPANY A  57638232  0.12322
1  BANANA 1 COMPANY B  12946201  0.02768
2    ORANGE COMPANY C   8354229  0.01786

【讨论】:

这个解决方案是迄今为止最好的。但是,该解决方案是否会替换以前存在的任何其他列?我的原始数据框有 3 列。 它不会替换,它会创建一个新的DataFrame。如果愿意,我可以更新我的答案以分配回原始 df? 感谢编辑!这正是我想要的。【参考方案3】:

您可以使用向后看和向前看运算符。

''.join(re.findall(r'(?<=\s2)(.*)(?=stocks)',string)).replace(' ','')

这会捕获两个空格和单词stocks之间的所有字符,并将所有空格替换为null。

另一种使用拆分的解决方案

df["NAME"].apply(lambda x:x[x.find('  ')+2:x.find('stocks')-1].replace(' ',''))

参考:-

    Look_behind

【讨论】:

或者他可以只做.split(' ')[1].split()[0],这比正则表达式(第一个分割中的2个空格)快得多 @Mataunited17 你能告诉我你想做什么吗?应该可以正常工作 @Nenri 我做了df['NAME'].str.split(' ')[1].split()[0] 这给了我错误:'list' 对象没有属性'split'。这很奇怪,因为我有一个数据框。 是的,.str 应该会返回一个字符串 @Justice_Lords 当我将您的第二个解决方案应用于我的原始数据框时,当名称很长时结果很奇怪。有没有办法来解决这个问题?我认为这与x:x[x.find(' ')+2:x.find('stocks')+2 部分有关【参考方案4】:

你可以试试

df['STOCKS'] = df['NAME'].str.split(',')[2].replace(' ', '')
df['NAME'] = df['NAME'].str.split(',')[0]

【讨论】:

谢谢,但他的字符串中仍然没有逗号,你应该按空格分隔,因为一个有2个空格,它应该是.split()[3].split()[0] 抱歉我忘记改了 @Vaghinak 这也不起作用。我收到错误消息:“列表”对象没有属性“替换” @Mataunited17 '因为你需要分割空间,是的,这个答案是错误的,他忘记了很多事情【参考方案5】:

这可以在不使用正则表达式的情况下使用 split 来完成。

df['STOCKS'] = df['NAME'].apply(lambda x: ''.join(x.split('  ')[1].split(' ')[:-1]))
df['NAME'] = df['NAME'].str.replace(r'\s?\d+(?:\s\d+).*', '')

【讨论】:

以上是关于使用正则表达式在双倍空格后提取整数的主要内容,如果未能解决你的问题,请参考以下文章

在 Bigquery 中看到“数字 + 一个字母 + [逗号或空格]”后提取字符串的正则表达式

正则表达式如何换行且有空格提取

正则表达式查找带空格的整数中的无效字符

python 正则表达式re.sub()提取字符串以及去除空格

如何在 Hive 中使用正则表达式来提取第二个整数? [关闭]

Pyspark SparkSQL 正则表达式在空格前获取子字符串