Как разделить адреса без запятых и нестандартные макеты во фрейме данных Pandas?

У меня есть такой столбец в фрейме данных (он включает в себя гораздо больше адресов):

Адрес 287 Андовер Пл Роббинсвилл, Нью-Джерси 08691 1 Оксфорд, Коннектикут, Принстон, Нью-Джерси 08550 244 N Post Rd Princeton Jct, Нью-Джерси 08550 3 Gates Ct West Windsor NJ 08550

Как я могу разделить эти адреса на 2 столбца, чтобы в одном столбце был номер и адрес, а в другом - город, штат, почтовый индекс, вот так:

адрес 1 Адрес 2 287 Андовер Пл. Роббинсвилл, Нью-Джерси 08691 1 Оксфордский карат Принстон Джкт, Нью-Джерси 08550 244 Н Пост Роуд Принстон Джкт, Нью-Джерси 08550 3 Ворота КТ Вест-Виндзор, Нью-Джерси 08550

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

# put zip code into separate column
        clean_df[['prop_addressLine1','Owner Zip']] = clean_df['Owner Address'].str.rsplit(' ', n=1, expand=True)

        # separate street, city, and state into their own columns:
        clean_df[['Owner Street','Owner City','Owner State']] = clean_df['prop_addressLine1'].str.rsplit(' ', n=2, expand=True)

Я думал разделить все на отдельные столбцы по пробелам, но есть нерегулярные пробелы, и я не придумал, как это сделать.

Анализ адресов в свободной форме — это задача НЛП.

Barmar 12.06.2024 19:39

Это невозможно сделать простым сопоставлением с образцом. Вам нужно что-то, что знает названия улиц и городов. В противном случае, как вы ожидаете, что он узнает, что N Post Rd Princeton не название улицы?

Barmar 12.06.2024 19:41
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
2
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Один из вариантов — использовать сокращения названий улиц (Ct/Pl/Rd) в качестве разделителей и извлечь две части:

df[['Address 1', 'Address 2']] = (df['Address'].str
                                  .extract('^(.*?(?:Pl|Ct|Rd)) (.*)$')
                                 )

Если вы хотите обрабатывать более сложные адреса, вам понадобится синтаксический анализатор. Например, с usaddress:

import usaddress

def address_split(addr):
    address1 = []
    address2 = []
    flag = False
    for val, k in usaddress.parse(addr):
        if k == 'PlaceName':
            flag = True
        if flag:
            address2.append(val)
        else:
            address1.append(val)
    return ' '.join(address1), ' '.join(address2)


df['Address 1'], df['Address 2'] = list(zip(*map(address_split, df['Address'])))

Выход:

                                Address       Address 1               Address 2
0  287 Andover Pl Robbinsville NJ 08691  287 Andover Pl   Robbinsville NJ 08691
1    1 Oxford Ct Princeton Jct NJ 08550     1 Oxford Ct  Princeton Jct NJ 08550
2  244 N Post Rd Princeton Jct NJ 08550   244 N Post Rd  Princeton Jct NJ 08550
3      3 Gates Ct West Windsor NJ 08550      3 Gates Ct   West Windsor NJ 08550

Промежуточный с usaddress.parse:

# usaddress.parse('244 N Post Rd Princeton Jct NJ 08550')

[('244', 'AddressNumber'),
 ('N', 'StreetNamePreDirectional'),
 ('Post', 'StreetName'),
 ('Rd', 'StreetNamePostType'),
 ('Princeton', 'PlaceName'),
 ('Jct', 'PlaceName'),
 ('NJ', 'StateName'),
 ('08550', 'ZipCode')]

Спасибо за ответ! Если я буду использовать сокращения улиц, мне придется перечислить каждое из них. Есть ли быстрый способ сделать это для больших наборов данных? Похоже, лучше всего подойдет парсер, так как этот список является лишь примером, и там сотни адресов с разными городами, сокращениями улиц и т. д. Если я воспользуюсь парсером, нужно ли мне устанавливать какие-либо дополнительные программы? Если да, то какое будет имя?

Christopher Avallon 12.06.2024 20:06

Не видя полного набора данных, сложно комментировать первый подход. Конечно, вам может понадобиться метод проб и ошибок. Что касается библиотеки, если вы перейдете по ссылке в моем ответе, вы увидите, что ее нужно установить с помощью pip install usaddress.

mozway 12.06.2024 20:19

Спасибо! Да, я понял это после того, как отправил обратно свой ответ. Я пойду этим путем. Я думаю, что это будет лучший выбор для данного сценария.

Christopher Avallon 12.06.2024 20:52

Другие вопросы по теме