使用正则表达式在双倍空格后提取整数
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' fordf['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()提取字符串以及去除空格