Получить почтовый индекс из столбца полного адреса в dataframe с помощью regex str.extract() и добавить в качестве нового столбца в pandas

#python #regex #pandas #dataframe #postal-code

#python #регулярное выражение #pandas #dataframe #почтовый индекс

Вопрос:

У меня есть фрейм данных с полными адресами в столбце, и мне нужно создать отдельный столбец, содержащий только почтовый индекс из 5 цифр, начинающийся с 7, в том же фрейме данных. Некоторые адреса могут быть пустыми или почтовый индекс не найден.

Как мне разделить столбец, чтобы просто получить почтовый индекс? почтовый индекс, начинающийся с 7, например, 76000, является почтовым индексом в индексе 0

 MedicalCenters["Postcode"][0]
Location(75, Avenida Corregidora, Centro, Delegación Centro Histórico, Santiago de Querétaro, Municipio de Querétaro, Querétaro, 76000, México, (20.5955795, -100.39274225, 0.0))
  

Пример данных

     Venue         Venue Latitude Venue Longitude Venue Category Address
0 Lab. Corregidora  20.595621   -100.392677      Medical Center Location(75, Avenida Corregidora, Centro, Delegación Centro Histórico, Santiago de Querétaro, Municipio de Querétaro, Querétaro, 76000, México, (20.5955795, -100.39274225, 0.0))
  

Я пытался использовать regex, но я получаю и ошибка

 # get zipcode from full address
import re 
MedicalCenters['Postcode'] = MedicalCenters['Address'].str.extract(r'bd{5}b', expand=False) 
  

ОШИБКА

 ---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-185-84c21a29d484> in <module>
      1 # get zipcode from full address
      2 import re
----> 3 MedicalCenters['Postcode'] = MedicalCenters['Address'].str.extract(r'bd{5}b', expand=False)

~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/strings.py in wrapper(self, *args, **kwargs)
   1950                 )
   1951                 raise TypeError(msg)
-> 1952             return func(self, *args, **kwargs)
   1953 
   1954         wrapper.__name__ = func_name

~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/strings.py in extract(self, pat, flags, expand)
   3037     @forbid_nonstring_types(["bytes"])
   3038     def extract(self, pat, flags=0, expand=True):
-> 3039         return str_extract(self, pat, flags=flags, expand=expand)
   3040 
   3041     @copy(str_extractall)

~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/strings.py in str_extract(arr, pat, flags, expand)
   1010         return _str_extract_frame(arr._orig, pat, flags=flags)
   1011     else:
-> 1012         result, name = _str_extract_noexpand(arr._parent, pat, flags=flags)
   1013         return arr._wrap_result(result, name=name, expand=expand)
   1014 

~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/strings.py in _str_extract_noexpand(arr, pat, flags)
    871 
    872     regex = re.compile(pat, flags=flags)
--> 873     groups_or_na = _groups_or_na_fun(regex)
    874 
    875     if regex.groups == 1:

~/opt/anaconda3/lib/python3.7/site-packages/pandas/core/strings.py in _groups_or_na_fun(regex)
    835     """Used in both extract_noexpand and extract_frame"""
    836     if regex.groups == 0:
--> 837         raise ValueError("pattern contains no capture groups")
    838     empty_row = [np.nan] * regex.groups
    839 

ValueError: pattern contains no capture groups

time: 39.5 ms
  

Ответ №1:

Вам нужно добавить круглые скобки, чтобы сделать его группой

 MedicalCenters['Address'].str.extract(r"b(d{5})b")
  

Ответ №2:

Вы можете попробовать сначала разделить строку, тогда будет легче сопоставить почтовый индекс:

 address = '75, Avenida Corregidora, Centro, Delegación Centro Histórico, Santiago de Querétaro, Municipio de Querétaro, Querétaro, 76000, México, (20.5955795, -100.39274225, 0.0'

matches = list(filter(lambda x: x.startswith('7') and len(x) == 5, address.split(', '))) # ['76000']
  

Таким образом, вы можете заполнить свой DataFrame с помощью:

 df['postcode'] = df['address'].apply(lambda address: list(filter(lambda x: x.startswith('7') and len(x) == 5, address.split(', ')))[0])
  

Ответ №3:

Данные адреса были объектом, поэтому регулярное выражение не работало

 MedicalCenters.dtypes
Venue               object
Venue Latitude     float64
Venue Longitude    float64
Venue Category      object
Health System       object
geom                object
Address             object
Postcode            object
dtype: object
time: 6.41 ms
  

после преобразования объекта в строку :

 MedicalCenters['Address'] = MedicalCenters['Address'].astype('str') 
  

Я смог применить измененное регулярное выражение благодаря glam

 # get zipcode from full address
import re 
MedicalCenters['Postcode'] = MedicalCenters['Address'].str.extract(r"b(d{5})b")
  

ВЫВОД