字符串在python中包含两个df



我有两个df和两个字符串列,如下所示:

Df1:原始df有2000行名称

Id    Name
1     Paper
2     Paper
3     Scissors
4     Mat
5     Cat
6     Cat

第二个Df:原始Df有1000+项目名称

Item_ID   Item_Name
1         Paper Bag
2         wallpaper
3         paper
4         cat cage

我需要位于Item_Name列的Name列中的字符串

第一种方法:使用str.contains:

如果字符串是一列和两个字符串,我知道如何匹配,如下所示:

df[df['Name'].str.contains("paper|cat", na=False)]

但是当有两列字符串(名称和项目名称(要匹配时该怎么办?

第二种方法:Fuzzywuzzy

matched = []
for row in df1.index:
name = df1.get_value(row,"Name")
for columns in df2.index:
item_name=df2.get_value(columns,"Item_Name")
matched_token=fuzz.token_sort_ratio(name,item_name)
if matched_token> 80:
matched.append([name,item_name,matched_token])

问题是,它会很慢,而且我想要的输出比我从fuzzywuzzy得到的要多一点。输出看起来像:

Id Name     Item_ID
1  Paper     1,2,3
2  Paper     1,2,3
3  Scissors  NA 
4  Mat       NA 
5  Cat       4
6  Cat       4 

总结

  1. 如果它们是两个具有不同列名的df,如何执行str.contains
  2. 如何转换df以获得上述预期输出

您可以将pd.Series.apply与自定义函数一起使用:

def matcher(x):
res = df2.loc[df2['Item_Name'].str.contains(x, regex=False, case=False), 'Item_ID']
return ','.join(res.astype(str))
df1['Item_ID'] = df1['Name'].apply(matcher)
print(df1)
Id      Name Item_ID
0   1     Paper   1,2,3
1   2     Paper   1,2,3
2   3  Scissors        
3   4       Mat        
4   5       Cat       4
5   6       Cat       4

有一些方法可以提高效率:

  • 仅处理df1['Name']:apply中的唯一项是行循环
  • 使用列表综合而不是pd.Series.apply。两者都是Python级别的循环,但列表理解通常优于Pandasstr方法

但以上并不能提高算法的复杂性。为了获得数量级的更好改进,您应该考虑基于trie的算法,例如使用Aho–Corasick算法的这个答案。

您可以在此处使用df.apply

def get_vals(df):
return ','.join(map(str, df2.loc[df2['Item_Name'].str.contains(df['Name'], case=False),]['Item_ID'].tolist()))
df1['Item_ID'] = df1.apply(get_vals, axis=1)

输出:

Id     Name  Item_ID
1     Paper   1,2,3
2     Paper   1,2,3
3  Scissors        
4       Mat        
5       Cat       4
6       Cat       4

相信这会给你想要的结果

df=pd.DataFrame({'ID':[1,2,3,4,5,6],'Name':['paper','paper','scissors','mat','cat','cat']})
df1=pd.DataFrame({'ID':[1,2,3,4],'Name':['paper bag','wallpaper','paper','cat cage']})

import numpy as np
def lookup_prod(ip):
lst=[]
for idx,row in df1.iterrows():
if ip in row['Name']:
lst.append(row['ID'])    
if not lst:
return np.NaN
return lst
df['Item_ID'] = df['Name'].apply(lookup_prod)

输出:

ID  Name         Item_ID
0   1   paper     [1, 2, 3]
1   2   paper     [1, 2, 3]
2   3   scissors    NaN
3   4   mat         NaN
4   5   cat         [4]
5   6   cat         [4]

最新更新