是否有可能按列表过滤 pandas?

Is there any possibility to filter pandas by list?

我有一个包含列 product_idkeyword 的 df。我通过 group_name, group in s.groupby('product_id') 迭代产品 ID,在这一步中,我想保留包含搜索列表中所有元素的组。 例如:

我的搜索列表 = ['land', 'cruiser']

所以在输出中,我想要这个:

我试过了

data[data["keywords"].isin(search_words)]

但此方法保留所有组,如果它包含列表中的至少一个元素,而 I 组必须包含搜索列表中的所有元素。

对于不同的答案(在一行中!):

import pandas as pd
s = pd.DataFrame({'product_id': [1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4],
                  'keywords': ["land", "cruiser", "land", "cruiser", "land",
                               "land", "land", "cruiser", "cruiser", "land", "cruiser"]})

search_words = ['land', 'cruiser']

s[[(all(p in x for p in search_words)) \
   for x in s.merge(s.groupby("product_id").apply(
           lambda x: list(set(x["keywords"]))).to_frame(). \
               rename(columns={0: "grouped"}), left_on="product_id",
               right_index=True)["grouped"]]]
#Out: 
#    product_id keywords
#0            1     land
#1            1  cruiser
#2            1     land
#3            1  cruiser
#4            1     land
#9            4     land
#10           4  cruiser

编辑

我刚刚使用了 pandas groupby filtration,并意识到在这里使用它会简单得多。返回的dataframe和上面的完全一样,只是代码少了很多!

s.groupby("product_id").filter(lambda x: all(p in list(set(x["keywords"])) for p in search_words))

这里的核心逻辑摘自

我创建了一些辅助变量,而不是 one-liner——我创建了一系列 product_id 及其所有相关的搜索词 (product_keywords)。然后我制作了一个包含所有关键字的所有 product_id 的系列(守护者)。最后,我使用 isin() 方法测试数据帧行是否在该列表中有 product_id。

这会保留组中包含所有搜索词的所有词;因此,如果第 1 组有“land”和“cruiser”以及其他词,则这会包含所有术语。

df = pd.DataFrame({"product_id": [1,1, 2, 3, 1, 2, 3],
                   "keywords": ["land", "barn", "land", "land", "cruiser", "barn", "cruiser"]})

search_list = set(['land', 'cruiser'])

product_keywords = df.groupby("product_id").apply(lambda x: list(set(x["keywords"])))

product_keywords
# product_id
# 1    [barn, cruiser, land]
# 2             [barn, land]
# 3          [cruiser, land]

keepers = product_keywords[product_keywords.apply(lambda found_terms: all(search_term in found_terms for search_term in search_list))]

keepers
# product_id
# 1    [barn, cruiser, land]
# 3          [cruiser, land]


df.loc[df['product_id'].isin(keepers.index)]  
#    product_id keywords
# 0           1     land
# 1           1     barn
# 3           3     land
# 4           1  cruiser
# 6           3  cruiser