使用:Python 3.7.3,Pandas 0.24.2
我正在使用Pandas数据框在Python中编写一些搜索功能。
我有一行代码可以搜索包含列表中所有关键字的结果:
processed = df.loc[(df.Keywords.str.contains("magnetic")) & (df.Keywords.str.contains("board")) & (df.Keywords.str.contains("white"))]
我需要使搜索词动态化,即根据其中包含任意数量的单词的变量生成与此行等效的内容。
我设法用正则表达式对此进行了编码,但是它比使用上面的方法要慢得多。我可以简单地传递一个搜索词,但不能传递可变数量的词。
我还必须考虑以下事实:搜索项可能是部分的,即如果行包含“磁铁”等,则应返回“ agnet”的搜索项。
非常感谢您收到任何选项。
要澄清:
我已经尝试使用诸如:
的选项processed = df[df['Keywords'].str.contains('|'.join(search_list))]
不幸的是,它返回包含任何搜索词的任何行。即磁性OR
板OR
白色。我需要返回的行包含磁性AND
板AND
白色。在亚马逊上搜索产品图片,这将是最接近的比较。
以下建议的结果:
我已经使用以下代码测试了以下提供的选项:
search_terms =“磁性板白” search_terms = search_terms.lower() search_list = search_terms.split()
start_time = time.time()
processed = df.loc[(df.Keywords.str.contains("magnetic")) & (df.Keywords.str.contains("board")) & (df.Keywords.str.contains("white"))]
print("--- Original %s seconds ---" % (time.time() - start_time))
start_time = time.time()
mask = pd.concat([df['Keywords'].str.contains(x) for x in search_list], axis=1).all(axis=1)
processed = df[mask]
print("--- Concat %s seconds ---" % (time.time() - start_time))
start_time = time.time()
processed = df[np.logical_and.reduce([df['Keywords'].str.contains(x) for x in search_list])]
print("--- Numpy reduce %s seconds ---" % (time.time() - start_time))
在我使用的数据集上,我得到了以下结果:
--- Original 0.09292888641357422 seconds ---
--- Concat 0.09293532371520996 seconds ---
--- Numpy reduce 0.11991643905639648 seconds ---
因此,我选择使用@jezrael建议的Concat DataFrame.all方法。
非常感谢大家的支持。
答案 0 :(得分:2)
对列表理解中的所有掩码使用np.logical_and.reduce
,然后进行过滤:
processed = df[np.logical_and.reduce([df['Keywords'].str.contains(x) for x in search_list])]
使用concat
和DataFrame.all
的另一种解决方案:
mask = pd.concat([df['Keywords'].str.contains(x) for x in search_list], axis=1).all(axis=1)
processed = df[mask]
答案 1 :(得分:1)
尝试将所有字符串插入列表中,并将str.contains与join一起使用
list_str=['board', 'white', 'magnetic']
df = df[df['Keyword'].str.contains('|'.join(list_str))]
如果您想最匹配
results= df[np.logical_and.reduce([df['Keywords'].str.contains(x) for x in list_str])]
答案 2 :(得分:1)
我可以使用numpy.logical_and
和reduce
来做到这一点:
df = pd.DataFrame({'Keywords': ['whiteboard', 'white', 'board', 'magnetic whiteboard', 'magnet']})
search = ['white', 'board', 'magnet']
df[np.logical_and.reduce([(df.Keywords.str.contains(s)) for s in search])]
结果:
Keywords
3 magnetic whiteboard
我尚未测试过速度,但与正则表达式解决方案相比,我认为它的性能会很好。