Python Pandas несколько условий поиска - PullRequest
1 голос
/ 10 июля 2019

Использование: Python 3.7.3, Pandas 0.24.2

Я нахожусь в процессе написания некоторых функций поиска в Python с использованием фреймов данных Pandas.

У меня есть строка кода, котораяпоиск результатов, содержащих все ключевые слова в списке:

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 Белая.Поиск изображений для продуктов на Amazon, это было бы самым близким сравнением.

Результаты из приведенных ниже предложений:

Я проверил представленные ниже варианты со следующим кодом:

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

Поэтому я решил использовать метод Concat DataFrame.all, предложенный @ jezrael.

Большое спасибо всем за поддержку.

Ответы [ 3 ]

2 голосов
/ 10 июля 2019

Используйте 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 голос
/ 10 июля 2019

Я бы сделал это, используя 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

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

1 голос
/ 10 июля 2019

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