У меня есть такой столбец в фрейме данных (он включает в себя гораздо больше адресов):
Как я могу разделить эти адреса на 2 столбца, чтобы в одном столбце был номер и адрес, а в другом - город, штат, почтовый индекс, вот так:
Я пытался сделать это, разделяя все пробелом справа, но некоторые города включают в свои названия два слова, и поэтому этот способ не работает.
# 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)
Я думал разделить все на отдельные столбцы по пробелам, но есть нерегулярные пробелы, и я не придумал, как это сделать.
Это невозможно сделать простым сопоставлением с образцом. Вам нужно что-то, что знает названия улиц и городов. В противном случае, как вы ожидаете, что он узнает, что N Post Rd Princeton не название улицы?






Один из вариантов — использовать сокращения названий улиц (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')]
Спасибо за ответ! Если я буду использовать сокращения улиц, мне придется перечислить каждое из них. Есть ли быстрый способ сделать это для больших наборов данных? Похоже, лучше всего подойдет парсер, так как этот список является лишь примером, и там сотни адресов с разными городами, сокращениями улиц и т. д. Если я воспользуюсь парсером, нужно ли мне устанавливать какие-либо дополнительные программы? Если да, то какое будет имя?
Не видя полного набора данных, сложно комментировать первый подход. Конечно, вам может понадобиться метод проб и ошибок. Что касается библиотеки, если вы перейдете по ссылке в моем ответе, вы увидите, что ее нужно установить с помощью pip install usaddress.
Спасибо! Да, я понял это после того, как отправил обратно свой ответ. Я пойду этим путем. Я думаю, что это будет лучший выбор для данного сценария.
Анализ адресов в свободной форме — это задача НЛП.