Как я могу найти указанные строки, соответствующие шаблонам фильтров с Pandas - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть набор данных pandas с именем 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
5  Jonas 5         ...                         NaN
6  Jonas 5         ...                Chris Archie

В качестве входных данных я хочу предоставить набор строк для фильтрации строкпо этим ключевым словам.Я думал об использовании списка:

list = ["Chris", "Betty"]

Я обнаружил, что могу отфильтровать строки, если я сделаю список строк с записями, разделенными "|":

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

Вместо этого я хочу:

  1. фильтрация, содержащая ТОЛЬКО элементы списка, и

  2. фильтрация, содержащая AT LEASTзаписи списка

Для 1. результат должен быть

3 Jonas 3 ... Betty Chris

Для 2. результат должен быть:

2  Jonas 2         ...          Chris Betty Archie
3  Jonas 3         ...                 Betty Chris

Я обнаружил, что следующее в основном помогло 2.

a = tf["Keywords"].str.contains("Chris")
b = tf["Keywords"].str.contains("Betty")
tf[a&b]

Однако мне нужно сделать это универсальным, поскольку длина списка и его записи могут различаться.У меня была неуклюжая идея с циклом пересечения каждых двух последовательных записей в списке, но это не сработало:

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

Я ценю вашу помощь.

Ответы [ 4 ]

0 голосов
/ 29 ноября 2018
def compset(x, mylist):
    y = set(x.lower().split())
    if len(y.intersection(mylist)) > 1:  # == 2 for exact match
        return True
    else:
        return False

mylist=set('chris betty'.lower().split())

df['Keywords'].apply(compset, args=(mylist,))
0 голосов
/ 20 ноября 2018

Я думаю, что это больше, что вы ищете, ячейки данных pandas могут содержать списки:

import pandas

# Create a test dataframe
df = pandas.DataFrame(
    [
        {"name": "A", "keywords": "Something SomethingElse"},
        {"name": "B", "keywords": "SomethingElse Tada"},
        {"name": "C", "keywords": "Something SomethingElse AndAnother"},
    ]
)

# Split the keywords INSIDE the cell
df["keywords"] = df["keywords"].apply(lambda row: row.split(" "))

# Filter for a specific keyword
filter_terms = ["Something"]
filtered = df.loc[df["keywords"].apply(lambda row: any([term in filter_terms for term in row]))]

# Show the filtered results
print(filtered)
0 голосов
/ 20 ноября 2018

Просто добавьте подход, который вы подразумевали в своем сообщении с помощью

Просто имитированный фрейм данных:

>>> df
      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

Использование str.contains при использовании имен с | разделенными ..

>>> df[df.Keywords.str.contains("Chris|Betty", na=False)]
      Name            Keywords
0  Jonas 0        Archie Betty
2  Jonas 2  Chris Betty Archie
3  Jonas 3         Betty Chris

Теперь, если у нас есть несколько поисков по именам, тогда применяем поиск по шаблону путем построения регулярного выражения, объединяя слова в pattern с |:

>>> pattern
['Chris', 'Betty']

>>> df[df.Keywords.str.contains('|'.join(pattern), na=False)]
      Name            Keywords
0  Jonas 0        Archie Betty
2  Jonas 2  Chris Betty Archie
3  Jonas 3         Betty Chris
0 голосов
/ 20 ноября 2018

Примечание:

Не используйте имя переменной list, потому что кодовое слово Python.


Решение, если все ключевые слова имеюттолько одно слово, без пробелов между:

Вы можете разбить все слова по пробелам и преобразовать их в set с, так что возможно сравнение по набору, преобразованному из списка 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

Более общее решение работы с несколькими словами в ключевых словах:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...