字符串在python中包含两个df之间

字符串在python中包含两个df之间,python,string,pandas,performance,string-matching,Python,String,Pandas,Performance,String Matching,我有两个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 我需要Name列中的字符串,它

我有两个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
我需要
Name
列中的字符串,它们位于Item\u Name

第一种方法:使用
str.contains

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

df[df['Name'].str.contains("paper|cat", na=False)]
但是,当有两列字符串(name和Item_name)需要匹配时,该怎么办

第二种方法:
fuzzyfuzzy

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])
问题将是,它将是缓慢的,我想要的是我从FuzzyWozzy得到的更多的小输出。输出如下所示:

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 
总结

  • 如果str.contains是两个具有不同列名的df,如何执行
  • 如何转换df以获得上述预期输出
  • 您可以与自定义函数一起使用:

    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级别的循环,但列表理解通常优于Pandas
      str
      方法
    但上述情况并不能提高算法的复杂性。为了更好地提高数量级,您应该考虑基于TIE的算法,例如利用.</P> 输出:

     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]
    
    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。在此处应用

    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
    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]
    
    Id     Name  Item_ID
    1     Paper   1,2,3
    2     Paper   1,2,3
    3  Scissors        
    4       Mat        
    5       Cat       4
    6       Cat       4
    

    相信这会给你带来你想要的结果

    你的项目ID栏是String@min2bro,是的,
    Item\u ID
    在OP所需的输出中也是如此。@jpp:我会试试这个,然后回复你
    ,因为你提到它只在unique上起作用。不,我的帖子不是这么说的。它说,如果要提高性能,请先删除重复的值。我不能用
    匹配不同的Item_ID
    @RahulAgarwal来复制你的问题,不幸的是,我认为这超出了一个调整范围,最好问一个新问题(用一个完整的例子,让人们理解你的意思!)。得到一个错误:TypeError:(“'Series'对象是可变的,因此不能散列的”,u'发生在索引0')它给了我所有行作为南。在您的示例中,两个df的列名都是相同的。你能修改一下吗?这样我就可以理解你在代码中引用的ID和名称了