【问题标题】:Python Pandas multiple search termsPython Pandas 多个搜索词
【发布时间】:2023-03-15 06:27:01
【问题描述】:

使用: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))]

不幸的是,这将返回包含任何搜索词的任何行。即磁性OROR 白色。我需要返回包含 Magnetic AND Board AND White 的行。在亚马逊上搜索产品的图片,这将是最接近的比较。

以下建议的结果:

我已经使用以下代码测试了下面提供的选项:

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 方法。

非常感谢大家的支持。

【问题讨论】:

  • 构建一个以数据框、列和列表作为输入的函数。然后使用链接答案中的方法返回您想要的行。类似:def search_string(dataframe, col, words)。然后作为正文return dataframe[dataframe[col].str.contains('|'.join(words))]
  • 我不认为这是链接问题的重复。 OP 正在搜索包含 all 搜索词的结果,链接的问题搜索了 any 搜索词。
  • 你是对的@thesilkworm,投票支持重新开放
  • @Matthew,您能否添加一些示例数据,以便我们为您重现答案。
  • 重新打开的问题

标签: python pandas search


【解决方案1】:

尝试在列表中插入所有字符串并将 str.contains 与连接一起使用

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])]

【讨论】:

  • 值得一提的是,这实际上构建了一个正则表达式,并利用contains 知道如何处理正则表达式。
  • 感谢您的选择。请参阅我在上面添加的说明 - 我正在查找列表中没有的所有术语。
【解决方案2】:

对列表理解中的所有掩码使用np.logical_and.reduce,然后过滤:

processed = df[np.logical_and.reduce([df['Keywords'].str.contains(x) for x in search_list])]

concatDataFrame.all 的另一种解决方案:

mask = pd.concat([df['Keywords'].str.contains(x) for x in search_list], axis=1).all(axis=1)
processed = df[mask]

【讨论】:

  • 非常感谢,我会在我的数据集上测试速度并告诉你结果。
  • 这两个选项都有效,我发现 concat dataframe.all 方法是我测试的数据集最快的。非常感谢您的支持。
【解决方案3】:

我会使用 numpy.logical_andreduce 来做到这一点:

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

我没有测试过速度,但我认为与正则表达式解决方案相比,它会表现得很好。

【讨论】:

  • 非常感谢,我会在我的数据集上测试速度并告诉你结果。
  • 很好的答案。我确实发现@jezrael 列出的 concat 方法更快,所以我接受了它作为答案,但认为它工作得很好。感谢您的帮助。
猜你喜欢
  • 2021-05-01
  • 2019-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多