Могу ли я использовать регулярное выражение для разделения столбца фрейма данных pandas только при первом совпадении?

#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.*)' .

Смотрите демонстрацию регулярных выражений.