최근, 한글 주소를 활용해 데이터를 모아야 하는 일이 있었고, 현재도 프로젝트는 진행 중에 있다. 수행해야 하는 것은 기존에 갖고 있는 한글주소를 가지고, 토지이음이라는 토지의 활용과 관련된 정부의 웹사이트에서 데이터를 취합하는 것을 목표로 하고 있다.
결국, 기존 데이터와 새로운 곳의 데이터 형식에 대한 일치하는지, 일치하지 않다면 이를 어떻게 해결할 것인지가 필요하다. 이를 위해, 토지이음에서는 어떻게 데이터를 입력받고 있는지를 확인했다. 사이트에서는 아래와 같이 광역지자체를 선택하게끔 하고 있다.
한국에서 주소 관련 (수기입력을 하는)정보들은, 특히 광역지자체에 대해서는 저 위의 형식이 지켜지지 않는다. (예를 들면, '서울특별시'란 광역지자체도 '서울', '서울시' 등으로 다양하게 적음) 따라서, 기존에 갖고 있던 한글 주소 데이터를 확인하기 위해 살펴봤는데, 아니나다를까 아래 사진처럼 제각각으로 쓰여있다.
정보 조회를 위해서는 첫번째 사진처럼 통일된 형식이 필요한데, 그렇지 못한 상황에서 어떻게 해결해야 할까. 내가 생각한 방법은 다음과 같다.
1. 참고하기 위한 표준화된 리스트를 만든다.
2. 광역지자체 명명에 대한 일정한 규칙을 찾아 정규식을 만들어, 광역지자체만 찾는다.
3. 2단계에서 찾은 광역지자체에서 식별가능한 수준의 두 음절이 있는지를 확인해, 표준화된 광역지자체명으로 대체
이렇게만 설명하면, 어려우니 아래에서 하나씩 살펴보자.
1번은 크게 어렵지 않으므로, 제외하고 2번째 부터 살펴보자.
2. 광역지자체 명명에 대한 일정한 규칙을 찾아 정규식을 만들어, 광역지자체만 찾는다.
- 광역지자체는 크게 -도로 끝나거나, -시로 끝나는 특별시나 광역시 같은 곳들이다.
- 하지만, 강원도를 강원이라고 2글자로 줄여서 말하는 경우가 생긴다.
- 따라서, 정규식의 패턴은 ~도, ~시, ~@로 되는 정규식을 만든다. (Sido_pattern)
- 그리고 기존 데이터프레임의 주소에서 위 패턴으로 된 데이터를 찾아, 문자열로 반환한다. (Sido)
import re
Sido_pattern = r'(\w+[원,산,남,울,북,천,주,기,시,도,전,구])?'
for addr in df['address']:
Sido = re.search(Sido_pattern, addr).group()
3. 2단계에서 찾은 광역지자체에서 식별가능한 수준의 두 음절이 있는지를 확인해, 표준화된 광역지자체명으로 대체
- 광역지자체를 줄여 명명해도, 최소 2글자 이상은 됨 (e.g. 충남, 충북, 강원, 경기 ...)
- 그렇기 때문에 앞의 두글자만으로 모든 문자열을 구분가능할 것이라는 가설
- 1단계에서 만든 Sido_list의 표준명과 주소데이터 문자열과 비교(item.find(Sido[i])), 여기서 i는 첫 두글자만 할 것이기 때문에 0과 1만 들어감
- 위 2단계와 합쳐보면 아래처럼 작성 가능
import re
Sido_list =['서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시', '대전광역시',
'울산광역시', '세종특별자치시', '경기도', '강원도', '충청북도', '충청남도',
'전라북도', '전라남도', '경상북도', '경상남도', '제주특별자치도']
for addr in df['address']:
Sido = re.search(Sido_pattern, addr).group()
# 표준이름과 비교하기
for item in Sido_list:
if item.find(Sido[0]) != -1: # 첫글자가 표준이름 item 중에 있는지 확인
if item.find(Sido[1]) != -1: # 두번째 글자가 표준이름 item 중에 있는지 확인
Sido_new = item
print(Sido_new)
위 코드를 940여개의 데이터에 돌려본 결과, 2개 오류 발생건을 제외하면 잘 돌아가는 것을 확인할 수 있다. 다만, 실무적으로 활용할 때 오류 발생한 건들에 대해 다시 살펴보기 위해 예외처리 등 몇 가지 작업을 해주자.
- 오류가 발생했을 때, 처리할 수 있도록 try ~ except 사용.
- 발생한 오류의 위치와 데이터의 형태를 확인할 수 있게끔, 인덱스(ind)와 오류 리스트(error_list) 정의
- 그리고 이를 except절에서 ind, addr를 error_list에 넣고, for문 continue
import re
Sido_list =['서울특별시', '부산광역시', '대구광역시', '인천광역시', '광주광역시', '대전광역시',
'울산광역시', '세종특별자치시', '경기도', '강원도', '충청북도', '충청남도',
'전라북도', '전라남도', '경상북도', '경상남도', '제주특별자치도']
ind = 0
error_set = set()
for addr in df['address']:
Sido = re.search(Sido_pattern, addr).group()
for item in Sido_list:
try:
if item.find(Sido[0]) != -1:
if item.find(Sido[1]) != -1:
Sido_new = item
print(Sido_new)
ind += 1
except:
error_set.add((ind, addr))
continue
에러난 것들을 확인해보니까, 하나는 광역지자체가 누락된 경우이고 나머지 하나는 띄어쓰기를 해서 인식을 못한 경우였다. 좀 더 가다듬을 필요는 있겠지만, 급할 때는 실무적으로 활용은 가능할 듯하다.
Version
Python = 3.8 (64 bit)
참고:
파이썬 표준라이브러리, https://docs.python.org/3/library/re.html
우아한 형제들 블로그, "쉽고 재밌는 정규식 이야기", https://techblog.woowahan.com/2505/
당근마켓 블로그, "주소 인식을 위한 삽질의 기록", https://medium.com/daangn/%EC%A3%BC%EC%86%8C-%EC%9D%B8%EC%8B%9D%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%82%BD%EC%A7%88%EC%9D%98-%EA%B8%B0%EB%A1%9D-df2d8f82d25
수정사항
수정일시 | 문제 | 해결 |
2021-08-22 | error가 있으면, 루프를 돌면서 리스트에 중복 | 리스트 대신 set()를 사용하고, add로 추가 |
'Python > Data Prep' 카테고리의 다른 글
Selenium을 활용한 지자체 선거 당선인 데이터 가져오기 | Web Scraping (0) | 2021.10.16 |
---|---|
파이썬으로 여러 페이지에 있는 정부 보도자료 크롤링하기_페이지네이션 | Web Scraping (0) | 2021.10.04 |
금감원 XML 파일(corp_code) python으로 읽어내기 (0) | 2020.03.14 |
[Data Prep] 파이썬을 활용한 공공데이터API 접근하기_미세먼지 통계 | BeautifulSoup, Open API (0) | 2020.03.04 |
[Data Prep] 파이썬 Openpyxl을 이용한 보도자료 내용 저장하기 (0) | 2020.03.02 |