[Troubleshooting] GeoPy의 geocoding 처리 속도는 왜 느릴까?

young·2022년 9월 24일
4

회고 및 피드백

목록 보기
2/7
post-thumbnail

문제 상황

현재 진행중인 프로젝트에서, 공간 데이터 시각화를 위한 folium 패키지 사용을 위해 주소 데이터를 위도, 경도로 변환하는 geocoding을 사용하였다.
그러나 구글 코랩, 주피터 노트북, VScode 모두에서 15분이 넘어도 geocoding 변환 리스트가 생성되지 않았다.
현재 데이터는 9000행 이상의 주소 데이터이며, 지오코딩은 Geopy 모듈의 Nominatim API를 이용하였다.
변환 처리가 늦어지는 원인과 해결 방법을 탐색했다.

###### Nominatim을 이용한 지오코딩 코드 #######

#Geopy 모듈 설치
!pip install geopy

# 한국 주소에 맞는 지오코딩 함수 호출
from geopy.geocoders import Nominatim
geo_local = Nominatim(user_agent='South Korea')

# 위도, 경도 반환하는 함수
def geocoding(address):
    try:
        geo=geo_local.geocode(address)
        x_y =[geo.latitude,geo.longitude]
        return x_y

    except:
        return[0,0]

#위도, 경도 리스트 생성을 위한 빈 리스트 생성
latitude=[]
longitude=[]

#주소 데이터의 변환된 위도, 경도 리스트 생성
for i in address:
	latitude.append(geocoding(i)[0])
    longitude.append(geocoding(i)[1])

Nominatium 지오코딩 코드 참고 링크

[지오코딩 API: 파이썬] 주소로 위도 경도 찾기, 좌표로 주소 얻기

원인 탐색

geopy에서 데이터 프레임을 만들 때 어떻게 효율적으로 처리할 수 있을지 질문한 stack overflow 질문글

Nominatim의 느린 처리 속도

Nominatim 공식 문서GeoPy 공식 문서에 따르면,
GeoPy는 단순한 하나의 패키지가 아닌 공간 데이터 API의 모음으로, 지정한 API를 불러오는 기능이라고 한다.
그중 많이 사용되는 Nominatim은 무료 API지만, 대략적으로 초당 리퀘스트 1개를 처리하여 처리 속도가 현저히 느리다.

공식 문서에서도 대량의 공간 데이터를 지오코딩하고 싶은 경우 유료 API 사용을 고려하거나, Rate Limiter를 사용하여 time out error가 나는 데이터는 넘기는 방법을 권장하고 있다.
Rate Limiter 관련 문서


문제 해결 #1

무작정 기다리기

스택오버플로우의 질문글의 경우 10만건의 데이터 처리를 하는데 15시간 이상 소요되었다고 말했다.
10시간까지 기다려보고 안되면 종료하겠다는 생각으로 일단 기다려보았다.

최종적으로 대략 7시간을 소요하여 지오코딩한 리스트가 생성되었다.

새로운 문제 발생

생성한 데이터에서 동일 위도, 경도가 나타나거나, 위도, 경도가 0으로 코딩된 값들이 상당히 많이 나타났다.

위도, 경도값이 0으로 코딩된 경우

다른 주소값에서 위도, 경도가 동일하게 코딩된 경우

문제 해결을 위해 다른 방법으로 geocoding을 시도해보고자 한다.


문제 해결 #2

카카오맵 API 이용 방법

주소가 한글 주소이므로, 한국 주소의 좌표 변환은 한국 회사의 지도가 더 효율적일 것이라는 생각이 들어 카카오맵 API로 지오코딩을 시도했다.

import requests, json

# 카카오맵 API 요청 및 지오코딩 함수 임포트
def get_location(address):
  url = 'https://dapi.kakao.com/v2/local/search/address.json?query=' + address
  # 'KaKaoAK '는 그대로 두고 개인키만 지우고 입력
  headers = {"Authorization": "KakaoAK 카카오맵API키"}
  api_json = json.loads(str(requests.get(url,headers=headers).text))
  address = api_json['documents'][0]['address']
  crd = {"lat": str(address['y']), "lng": str(address['x'])} 
  address_name = address['address_name']

  return crd
# for문을 이용하여 각각의 주소값을 위도 경도로 변환 후 데이터프레임으로 생성
df_geo=pd.DataFrame(columns=['lat','lng'])

t1 = time.time()
for address in df['주소'] :
    crd = get_location(address)
    lat = crd.get('lat')
    lng = crd.get('lng')
    df=df_geo.append(pd.DataFrame([[lat,lng]],columns=['lat','lng']))

지오코딩 코드는 멋진 팀원분이 짜주신 코드와
[지오코딩 API: 파이썬] 주소로 위도 경도 찾기, 좌표로 주소 얻기
를 참고하여 작성하였다.


새로운 문제 발생

카카오맵 API의 요청 제한 횟수 때문인지 time out error와 connection error가 반복되었다.
전체 주소 데이터의 좌표 변환이 되지 않은 채로 에러가 발생하여 지오코딩된 리스트를 얻을 수 없었다.


문제 해결 #3

Google map API 이용 방법

대량 주소를 빠르게 변환해줄 수 있다는 구글맵 API를 이용하여 지오코딩을 시도했다.
Geopy 모듈이 아닌 google map 모듈을 이용하여 지오코딩을 시도했다.

결과

Nominatim에서 7시간이 소요된 것과 다르게, 구글맵 API를 이용하니 20분만에 9500개가 넘는 주소 데이터의 지오코딩을 성공할 수 있었다.


결론

유료는 유료인 이유가 있다

  • Nominatim은 무료이고 API 인증도 필요없지만, 그만큼 처리 속도가 느렸다. 100개 이상의 주소를 지오코딩하고 싶은 경우 다른 API 이용을 권장한다.
  • 카카오맵도 무료 API지만 요청 제한 수가 작아 많은 수의 주소를 변환하려는 경우 실패할 가능성이 높다.
  • 상업적 목적의 API 이용인 경우 당연히 비용을 지불해야 하지만,
    개인적 목적의 프로젝트에서 유료 API 이용이 부담스러운 경우더라도
    평가판을 제공하므로 이를 이용하는 것이 훨씬 효율적이다.
  • 데이터 크기에 따라 API 성능 차이가 크므로, 목적에 맞는 API를 사용하는 것을 권장한다.

코드 작성보다 프로그램을 쓰는 것이 좋을수도 있다

  • 지오코딩은 코드로 이용하는 경우 여러 문제가 발생할 가능성이 높아 이를 보완하기 위한 지오코딩용 프로그램들이 존재한다.
  • 프로그램을 쓰는 것이 더 효율적일 수 있다.
profile
한 걸음씩 쌓아가는 데이터 분석

2개의 댓글

comment-user-thumbnail
2022년 9월 25일

덕분에 새로운 것 배우고 갑니다 :)

1개의 답글