用熊猫计算另一列中的正则表达式匹配项
Posted
技术标签:
【中文标题】用熊猫计算另一列中的正则表达式匹配项【英文标题】:Count regex matches in one column by values in another column with pandas 【发布时间】:2020-09-01 04:03:56 【问题描述】:我正在使用 pandas,并且有一个数据框,其中包含一系列句子和说它们的人,如下所示:
sentence person
'hello world' Matt
'cake, delicious cake!' Matt
'lovely day' Maria
'i like cake' Matt
'a new day' Maria
'a new world' Maria
我想通过person
计算sentence
(例如cake
、world
、day
)中正则表达式字符串的非重叠匹配。注意sentence
的每一行可能包含多个匹配项(例如cake
):
person 'day' 'cake' 'world'
Matt 0 3 1
Maria 2 0 1
到目前为止,我正在这样做:
rows_cake = df[df['sentences'].str.contains(r"cake")
counts_cake = rows_cake.value_counts()
但是,这个str.contains
给了我包含cake
的行,但不是cake
的单个实例。
我知道我可以在rows_cake
上使用str.counts(r"cake")
。但是,在实践中,我的数据框非常大(> 1000 万行),并且我使用的正则表达式非常复杂,因此如果可能,我正在寻找更有效的解决方案。
【问题讨论】:
【参考方案1】:也许您应该首先尝试获取句子本身,然后使用re
来执行优化的正则表达式:
for row in df.itertuples(index=False):
do_some_regex_stuff(row[0], row[1])#in this case row[0] is a sentence. row[1] is person
据我所知,itertuples 非常安静(注释 1 here)。所以你唯一的优化问题是正则表达式本身。
【讨论】:
【参考方案2】:我想出了一个相当简单的解决方案。但不能声称它是最快或最有效的。
import pandas as pd
import numpy as np
# to be used with read_clipboard()
'''
sentence person
'hello world' Matt
'cake, delicious cake!' Matt
'lovely day' Maria
'i like cake' Matt
'a new day' Maria
'a new world' Maria
'''
df = pd.read_clipboard()
# print(df)
输出:
sentence person
0 'hello world' Matt
1 'cake, delicious cake!' Matt
2 'lovely day' Maria
3 'i like cake' Matt
4 'a new day' Maria
5 'a new world' Maria
.
# if the list of keywords is fix and relatively small
keywords = ['day', 'cake', 'world']
# for each keyword and each string, counting the occourance
for key in keywords:
df[key] = [(len(val.split(key)) - 1) for val in df['sentence']]
# print(df)
输出:
sentence person day cake world
0 'hello world' Matt 0 0 1
1 'cake, delicious cake!' Matt 0 2 0
2 'lovely day' Maria 1 0 0
3 'i like cake' Matt 0 1 0
4 'a new day' Maria 1 0 0
5 'a new world' Maria 0 0 1
.
# create a simple pivot with what data you needed
df_pivot = pd.pivot_table(df,
values=['day', 'cake', 'world'],
columns=['person'],
aggfunc=np.sum).T
# print(df_pivot)
最终输出:
cake day world
person
Maria 0 2 1
Matt 3 0 1
如果这似乎是一种好方法,特别是考虑到数据量,欢迎提出建议。渴望学习。
【讨论】:
【参考方案3】:由于这主要涉及字符串,我建议将计算从 Pandas 中取出 - 在大多数情况下,在字符串操作方面,Python 比 Pandas 更快:
#read in data
df = pd.read_clipboard(sep='\s2,', engine='python')
#create a dictionary of persons and sentences :
from collections import defaultdict, ChainMap
d = defaultdict(list)
for k,v in zip(df.person, df.sentence):
d[k].append(v)
d = k:",".join(v) for k,v in d.items()
#search words
strings = ("cake", "world", "day")
#get count of words and create a dict
m = defaultdict(list)
for k,v in d.items():
for st in strings:
m[k].append(st:v.count(st))
res = k:dict(ChainMap(*v)) for k,v in m.items()
print(res)
'Matt': 'day': 0, 'world': 1, 'cake': 3,
'Maria': 'day': 2, 'world': 1, 'cake': 0
output = pd.DataFrame(res).T
day world cake
Matt 0 1 3
Maria 2 1 0
测试速度,看看哪个更好。这对我和其他人也很有用。
【讨论】:
谢谢!这就说得通了。在这种情况下,strings
还可以包含一堆正则表达式吗?我使用的一些正则表达式非常复杂。
是的,你可以,只要确保你会调整你的正则表达式以适应。以上是关于用熊猫计算另一列中的正则表达式匹配项的主要内容,如果未能解决你的问题,请参考以下文章