Панды для сопоставления содержимого столбца с ключевыми словами (с пробелами и скобками) - PullRequest
1 голос
/ 03 октября 2019

Столбец во фрейме данных содержит ключевые слова, с которыми я хочу сопоставить.

Я хочу проверить, содержит ли каждый столбец какое-либо из ключевых слов. Если да, распечатайте их.

Попробовал ниже:

import pandas as pd
import re

Keywords = [

"Caden(S, A)",
"Caden(a",
"Caden(.A))",
"Caden.Q",
"Caden.K",
"Caden"
]

data = {'People' : ["Caden(S, A) Charlotte.A, Caden.K;", "Emily.P Ethan.B; Caden(a", "Grayson.Q, Lily; Caden(.A))", "Mason, Emily.Q Noah.B; Caden.Q - Riley.P"]}

df = pd.DataFrame(data)

pat = '|'.join(r"\b{}\b".format(x) for x in Keywords)

df["found"] = df['People'].str.findall(pat).str.join('; ')

print df["found"]

Возвращает Нан. Я предполагаю, что проблема заключается в пробелах и скобках в ключевых словах.

Как правильно получить идеальные результаты? Спасибо.

Caden(S, A); Caden.K
Caden(a
Caden(.A))
Caden.Q

Ответы [ 2 ]

3 голосов
/ 03 октября 2019

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

Смысл в том, что высначала нужно отсортировать ключевые слова по длине в порядке убывания (поскольку в них есть пробелы), затем вам нужно экранировать эти значения, так как они содержат специальные символы, затем необходимо изменить границы слова, чтобы использовать однозначный границы слов, (?<!\w) и (?!\w) (обратите внимание, что \b зависит от контекста).

Использование

pat = r'(?<!\w)(?:{})(?!\w)'.format('|'.join(map(re.escape, sorted(Keywords,key=len,reverse=True))))

См. онлайн-тест Python :

import re
Keywords = ["Caden(S, A)", "Caden(a","Caden(.A))", "Caden.Q", "Caden.K", "Caden"]
rx = r'(?<!\w)(?:{})(?!\w)'.format('|'.join(map(re.escape, sorted(Keywords,key=len,reverse=True))))
# => (?<!\w)(?:Caden\(S,\ A\)|Caden\(\.A\)\)|Caden\(a|Caden\.Q|Caden\.K|Caden)(?!\w)
strs = ["Caden(S, A) Charlotte.A, Caden.K;", "Emily.P Ethan.B; Caden(a", "Grayson.Q, Lily; Caden(.A))", "Mason, Emily.Q Noah.B; Caden.Q - Riley.P"]
for s in strs:
    print(re.findall(rx, s))

Выход

['Caden(S, A)', 'Caden.K']
['Caden(a']
['Caden(.A))']
['Caden.Q']
1 голос
/ 03 октября 2019

Эй, не знаю, является ли это решение оптимальным, но оно работает. Я просто заменил точку на 8, а '(' на 6 и ')' на 9, не знаю, почему этот символ игнорируется str.findall?

своего рода биекция между {8,6,9} и {'.', '(', ')'}

for i in range(len(Keywords)): 
    Keywords[i] = Keywords[i].replace('(','6').replace(')','9').replace('.','8')
for i in range(len(df['People'])): 
    df['People'][i] = df['People'][i].replace('(','6').replace(')','9').replace('.','8')

И затем вы применяете свою функцию

  pat = '|'.join(r"\b{}\b".format(x) for x in Keywords)
  df["found"] = df['People'].str.findall(pat).str.join('; ')

Последний шаг вернуть {{. ',' (',') '}

for i in range(len(df['found'])): 
  df['found'][i] = df['found'][i].replace('6','(').replace('9',')').replace('8','.')
  df['People'][i] = df['People'][i].replace('6','(').replace('9',')').replace('8','.')

Вуаля

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...