Как извлечь из датафрейма адреса с помощью библиотеки Natasha
У меня имеется датафрейм. С помощью библиотеки Natasha мне необходимо извлечь адреса и очистить от лишних данных, таких как Match(start=1, stop=7, fact=Addr и оставить только название города/улицы. В сети нашел это решение:
from natasha import AddrExtractor, MorphVocab
morph_vocab = MorphVocab()
extractor = AddrExtractor(morph_vocab)
text = "г Калининград, ул Гагарина,20"
matches = extractor(text)
for match in matches:
address = text[match.start:match.stop]
print(address)
однако, оно работает только для строковых данных и выдает последнее совпадение (ул Гагарина).Подскажите, пожалуйста, как преобразовать данный код для dataframe.
Код исходного датафрейма
import pandas as pd
df = pd.DataFrame([[1,'Bob', ' москва'],
[2,'Sally', 'отдых'],
[3,'Scott', ' хабаровск']],
columns=['id','name', 'street'])
df
Ответы (1 шт):
Примерно так это всё можно объединить:
# !pip install natasha
import pandas as pd
from natasha import AddrExtractor, MorphVocab
morph_vocab = MorphVocab()
extractor = AddrExtractor(morph_vocab)
def fix_addr(text):
matches = extractor(text)
return (', '.join(f'{match.fact.type or ""} {match.fact.value}' for match in matches)) or None
df = pd.DataFrame([[1,'Bob', ' москва'],
[2,'Sally', 'отдых'],
[3,'Scott', 'хабаровск'],
[4,'Вася', 'село Верхний Низ, ул. Ленина, д. 17']],
columns=['id','name', 'street'])
df['street1'] = df['street'].map(fix_addr)
df
| index | id | name | street | street1 |
|---|---|---|---|---|
| 0 | 1 | Bob | москва | москва |
| 1 | 2 | Sally | отдых | None |
| 2 | 3 | Scott | хабаровск | хабаровск |
| 3 | 4 | Вася | село Верхний Низ, ул. Ленина, д. 17 | село Верхний Низ, улица Ленина, дом 17 |
В вашем коде показывает только последний найденный элемент адреса из-за неправильной табуляции, нужно внести print в цикл, вот так:
for match in matches:
address = text[match.start:match.stop]
print(address) # <- правильная табуляция
Теперь напечатает все фрагменты. Ну и брать элемент можно проще, как у меня в коде выше, через match.fact.value, а не через срез. Ещё там есть match.fact.type с типом элемента (например, "город"), но он не всегда заполнен.

