#python #regex #pandas
Вопрос:
Столбец в моем фрейме данных содержит следующие данные о вкладе кампании, отформатированные одним из двух способов:
JOHN A. DONOR1234 W ROAD ST CITY, STATE 56789
И
JANE M. DONOR
1234 W ROAD ST
CITY, STATE 56789
Я хочу разделить этот столбец на два. Первый столбец должен быть именем донора. Второй столбец должен быть адресом.
В настоящее время я использую следующий regex
код, чтобы попытаться выполнить это:
url = ("http://www.voterfocus.com/CampaignFinance/candidate_pr.php?op=rpamp;e=8amp;c=munmiamibeachamp;ca=64amp;sdc=116amp;rellevel=4amp;dhc=774amp;committee=N")
dfs = pd.read_html(url)
df = dfs[0]
df['Contributor'].str.split(r'dd?', expand=True)
Но вместо разделения после первого совпадения и выхода — как я и предполагал — регулярное выражение, похоже, продолжает сопоставление и разделение. Мой вывод должен выглядеть следующим образом:
Col1 Col2
JOHN A. DONOR 1234 W ROAD ST CITY, STATE 56789
Комментарии:
1. Пожалуйста, включите все примеры того, как выглядят данные. Не оставляйте нас в догадках.
Ответ №1:
это может быть намного проще. Вы можете использовать строковые методы. Например, я думаю, что это то поведение, которое вы хотите:
import pandas as pd
s = """JOHN A. DONOR
1234 W ROAD ST
CITY, STATE 56789"""
df = pd.DataFrame([s], columns=["donors"])
df.donors.str.split("n", 1, expand=True)
вывод:
0 1
0 JOHN A. DONOR 1234 W ROAD STnCITY, STATE 56789
Комментарии:
1. Ясно, что я неправильно задал свой вопрос. Не всегда существует новый разрыв строки между именем и адресом — вот почему я попытался использовать регулярное выражение на основе начальных номеров адресов, поскольку это был единственный способ разделить данные, которые казались применимыми в каждом случае.
Ответ №2:
Решение для разделения
Вы можете использовать
df['Contributor'].str.split(r'(?<=D)(?=d)', expand=True, n=1)
Регулярное (?<=D)(?=d)
выражение находит местоположение между нецифровым символом char ( D
) и цифрой char ( d
), разбивает там строку и выполняет эту операцию только один раз (из-за n=1
).
Альтернативное решение
Вы можете сопоставлять и записывать имена до первого числа, а затем записывать весь текст, который остается после и включая первую цифру, используя
df['Contributor'].str.extract(r'(?P<Name>D*)(?P<Address>d.*)', expand=True)
# => Name # Address
# 0 Contributor CHRISTIAN ULVERT 1742 W FLAGLER STMIAMI, FL 33135
# 1 Contributor Roger Thomson 4271 Alton Miami Beach , FL 33140
# 2 Contributor Steven Silverstein 691 West 247th Street Bronx , NY 10471
# 3 Contributor Cathy Raduns 691 West 247th Street Bronx, NY 10471
# 4 Contributor Asher Raduns-Silverstein 691 West 247th StreetBRONX, NY 10471
(?P<Name>D*)(?P<Address>d.*)
Шаблон означает
(?P<Name>D*)
— Группа «Имя»: ноль или более символов, отличных от цифр(?P<Address>d.*)
— Группа «Адрес»: цифра, а затем любой ноль или более символов, кроме символов разрыва строки.
Если в строке есть разрывы строк, добавьте (?s)
в начале шаблона, т. е. r'(?s)(?P<Name>D*)(?P<Address>d.*)'
.
Смотрите демонстрацию регулярных выражений.