如何使用Pandas查找指定的字符串匹配过滤器模式

Jon*_*nas 6 python pandas

tf有一个叫做pandas的数据集,它有一个包含空格分隔关键字的列,标题为"关键字":

Name         ...                    Keywords
0  Jonas 0         ...                Archie Betty
1  Jonas 1         ...                      Archie
2  Jonas 2         ...          Chris Betty Archie
3  Jonas 3         ...                 Betty Chris
4  Jonas 4         ...                       Daisy
5  Jonas 5         ...                         NaN
6  Jonas 5         ...                Chris Archie
Run Code Online (Sandbox Code Playgroud)

作为输入,我想提供一组字符串来按这些关键字过滤行.我想过使用一个列表:

list = ["Chris", "Betty"]
Run Code Online (Sandbox Code Playgroud)

我发现我可以过滤行,如果我将列表作为一个字符串,其中的条目由"|"分隔:

t="|".join(list)

并在以下列中查找该列中的匹配项:

tf[tf["Keywords"].str.contains(t, na=False)]

这通过查找任何匹配内容进行过滤,因此输出为:

Name         ...                    Keywords
0  Jonas 0         ...                Archie Betty
2  Jonas 2         ...          Chris Betty Archie
3  Jonas 3         ...                 Betty Chris
6  Jonas 5         ...                Chris Archie
Run Code Online (Sandbox Code Playgroud)

我想要的是:

  1. 通过仅包含列表条目和来过滤

  2. 通过包含AT LEAST列表条目进行过滤

对于1.结果应该是

3 Jonas 3 ... Betty Chris

对于2.结果应该是:

2  Jonas 2         ...          Chris Betty Archie
3  Jonas 3         ...                 Betty Chris
Run Code Online (Sandbox Code Playgroud)

我发现以下基本上是2的技巧.

a = tf["Keywords"].str.contains("Chris")
b = tf["Keywords"].str.contains("Betty")
tf[a&b]
Run Code Online (Sandbox Code Playgroud)

但是,由于列表长度及其条目可能会有所不同,因此我需要将其设置为通用的.我有一个笨拙的想法,循环交叉每两个连续的列表条目,但这不起作用:

i = 0
while i < len(list)-1:
    a = tf["Keywords"].str.contains(list[i])
    b = tf["Keywords"].str.contains(list[i+1])
    tf = a & b
    i += 1
Run Code Online (Sandbox Code Playgroud)

我感谢您的帮助.

jez*_*ael 0

注意:

不要使用变量名list,因为Python代码字。


如果所有关键字只有一个单词且之间没有空格的解决方案:

您可以按空格分割所有单词并将它们转换为sets,因此可以通过从列表转换而来的集合进行比较L

L = ["Chris", "Betty"]
s = set(L)

arr = np.array([set(x.split()) if isinstance(x, str) else set([]) for x in tf["Keywords"]])
print (arr)
[{'Archie', 'Betty'} {'Archie'} {'Chris', 'Archie', 'Betty'}
 {'Chris', 'Betty'} {'Daisy'} set() {'Chris', 'Archie'}]

df1 = tf[arr == s]
print (df1)
      Name     Keywords
3  Jonas 3  Betty Chris

df2 = tf[arr >= s]
print (df2)
      Name            Keywords
2  Jonas 2  Chris Betty Archie
3  Jonas 3         Betty Chris
Run Code Online (Sandbox Code Playgroud)

处理关键字中多个单词的更通用的解决方案:

print (tf)
      Name                  Keywords
0  Jonas 0              Archie Betty
1  Jonas 1                    Archie
2  Jonas 2        Chris Betty Archie
3  Jonas 3               Betty Chris
4  Jonas 4  Daisy Chris Archie Betty
5  Jonas 5                       NaN
6  Jonas 5        Chris Archie Betty

L = ["Chris Archie", "Betty"]
s = set(L)

#create pattern with word boundaries
pat = '|'.join(r"\b{}\b".format(x) for x in L)

#extract all keywords and convert to sets
a = tf['Keywords'].str.findall('('+ pat + ')')
a = np.array([set(x) if isinstance(x, list) else set([]) for x in a])
#remove all matched keywords and remove possible traling whitespaces
b = tf['Keywords'].str.replace(pat, '').str.strip()

#compare only matched values and also empty value after replace
df1 = tf[(b == '') & (a == s)]
print (df1)
      Name            Keywords
6  Jonas 5  Chris Archie Betty

#same like one keyword solution
df2 = tf[a >= s]
print (df2)
      Name                  Keywords
4  Jonas 4  Daisy Chris Archie Betty
6  Jonas 5        Chris Archie Betty
Run Code Online (Sandbox Code Playgroud)