在dataframe python列中搜索单词
我有两个文本栏,我想知道一个栏中的单词是否出现在另一个栏中。我编写了下面的代码,它工作得很好,但是它可以检测字符串中是否存在单词。例如,它将在“ham”中找到“ha”。我想改用正则表达式,但我被卡住了。我遇到了这个问题,并查看了第二个答案,但我无法根据自己的目的修改它。我想做类似的事情 我将非常感谢您的帮助和/或任何指点在dataframe python列中搜索单词,python,regex,pandas,Python,Regex,Pandas,我有两个文本栏,我想知道一个栏中的单词是否出现在另一个栏中。我编写了下面的代码,它工作得很好,但是它可以检测字符串中是否存在单词。例如,它将在“ham”中找到“ha”。我想改用正则表达式,但我被卡住了。我遇到了这个问题,并查看了第二个答案,但我无法根据自己的目的修改它。我想做类似的事情 我将非常感谢您的帮助和/或任何指点 d = {'emp': ['abc d. efg', 'za', 'sdfadsf '], 'vendor': ['ABCD enterprise', 'za industri
d = {'emp': ['abc d. efg', 'za', 'sdfadsf '], 'vendor': ['ABCD enterprise', 'za industries', '' ]}
df = pd.DataFrame(data=d)
df['clean_empy_name']=df["emp"].str.lower().str.replace('\W', ' ')
def check_subset(vendor, employee):
s = []
for n in employee.split():
# n=" " + n +"[^a-zA-Z\d:]"
if ((str(n) in vendor.lower()) & (len(str(n))>1)):
s.append(n)
return s
check_subset("ABC-xy 54", "54 xy")
df['emp_name_find_in_vendor'] = df.apply(lambda row: check_subset(row['vendor'],row['clean_empy_name']), axis=1)
df
#########更新2
我更新了我的数据框,如下所示
d = {'emp': ['abc d. efg', 'za', 'sdfadsf ','abc','yuma'], 'vendor': ['ABCD enterprise', 'za industries', '','Person Vue\Cisco','U OF M CONTLEARNING' ]}
df = pd.DataFrame(data=d)
df['clean_empy_name']=df["emp"].str.lower().str.replace('\W', ' ')
我使用了第一个答案提供的代码,但失败了
'Person Vue\Cisco'
的情况下,它会抛出错误错误:错误转义\c
。如果我在'Person Vue\Cisco'
中删除\项,代码运行正常'U of M CONTLEARNING'
时,当它们明显不匹配时,将返回U
和M
是的,你可以!这将有点混乱,所以让我分几个步骤来构建: 首先,让我们为
check_子集(“ABC xy 54”,“54 xy”)
的单个案例创建一个正则表达式:
- 我们将使用
在re.findall(pattern,string)
string
- 正则表达式模式基本上会说“任意单词”:
- 对于“any”,我们使用
(或)运算符|
- 为了构造单词,我们需要使用括号将单词分组。。。然而,括号
创建了一个跟踪的组,因此我们可以稍后调用重用这些组,因为我们不感兴趣,我们可以通过添加(word)
创建一个非捕获组,如下所示:?:
(?:word)
- 对于“any”,我们使用
重新导入
关于findall('(?:54)|(?:xy)'ABC xy 54')
#->['xy','54']
现在,我们必须每次构造模式
:
- 分词
- 将每个单词包装在非捕获组中
(?:)
- 通过
|
re.findall(“|”).join([”(?:“+x+”)”表示“54 xy.split()”)中的x,'ABC xy 54')
一个次要的问题是,由于最后一行的供应商是空的,并且您似乎不希望匹配(从技术上讲,空字符串与所有内容都匹配),因此我们必须添加一个次要检查。因此,我们可以将您的函数重写为:
def check_subset_regex(vendor, employee):
if vendor == '':
return []
pattern = '|'.join(['(?:'+x+')' for x in vendor.lower().split(' ')])
return re.findall(pattern, employee)
然后我们可以用同样的方法:
df['emp_name_find_in_vendor_regex'] = df.apply(lambda row: check_subset_regex(row['vendor'],row['clean_empy_name']), axis=1)
最后一点意见是,您的解决方案匹配部分单词,因此员工Tom Sawyer将“Tom”与供应商“Atomic S.A.”匹配。我在这里提供的正则表达式函数不会将此作为匹配项,如果您想这样做,正则表达式将变得更加复杂
编辑:删除供应商的标点符号 您可以像对clean_employee所做的那样添加一个新列,也可以简单地将删除操作添加到函数中(您需要
导入字符串
,以获取字符串。标点符号
,或者只需在其中添加一个包含所有要替换符号的字符串):
本着教鱼的精神:),在正则表达式中,[]
表示这些字符中的任何一个。。。因此,[abc]
将与a | b | c
相同
因此,re.sub
行将用'
(其计算结果为!“\$%&\'()*+,-./:;?@[\]^ `{{124}
)字符替换出现的'
)字符(删除它们)
EDIT2:在每个搜索词的末尾添加一个非字母数字字符:
def check_subset_regex(vendor, employee):
if vendor == '':
return []
clean_vnd = re.sub('[' + string.punctuation + ']', '', vendor)
pattern = '|'.join(['(?:'+x+'[^a-zA-Z0-9]?)' for x in clean_vnd.lower().split(' ')])
return re.findall(pattern, employee)
在本例中,我们使用:-
^
作为[]
(称为字符类)中的第一个字符,表示除字符类中指定的字符以外的任何字符,例如[^abc]
将匹配任何非a
或b
或c
(因此d
,或空白,或
)
-和?
,这意味着前面的符号是可选的
所以,
[^a-zA-Z0-9]?
表示可选的单个非字母数字字符。我不希望在“原子”中找到“Tom”。您的解决方案看起来不错。让我理解它,我会接受它。感谢您的解释……这有助于……教我如何钓鱼!在检查子集正则表达式(“ABC xy 54!”,“54 xy”)的情况下,它不起作用
…当我进行搜索时,我可以使用特殊字符,因为它们可能表示句子的结尾或问题的结尾等。@Ni_Tempe在这种情况下,它不匹配,因为我们尚未从供应商处清除标点符号。是否要清除所有标点符号?我们可以先清除所有特殊字符。但我很好奇我们可以做一些类似于“search\u word=”“+search\u word+”[^a-zA-Z\d:]“
然后str.findall(search\u word)
的事情吗?你的意思是在单词末尾添加特殊字符的可能性?当然可以,请参见EDIT2:)
def check_subset_regex(vendor, employee):
if vendor == '':
return []
clean_vnd = re.sub('[' + string.punctuation + ']', '', vendor)
pattern = '|'.join(['(?:'+x+'[^a-zA-Z0-9]?)' for x in clean_vnd.lower().split(' ')])
return re.findall(pattern, employee)