working_helen
[데이터 수집] 주소 -> 위도/경도 전환 본문
데이터 수집 단계에서 학습한 내용 중 네번째로 주소 데이터를 위도/경도 값으로 전환하는 방법에 대해 공부해본다.
1. Geocoding 지오코딩
2. 위경도 변환 코드 분석
1. Geocoding 지오코딩
- 주소와 관련된 텍스트 데이터 (주소, 도로명, 산 이름 등 고유명칭)를 위도/경도 좌표 정보로 변환하는 것
- 네이버, 구글, 다음 등 위도와 경도 관련 서비스를 해주는 다양한 geocoding 오픈 API 존재한다.
- 본 프로젝트에서는 네이버 클라우드 플랫폼 지도 API(Geocoding OpenAPI)를 활용했다. NAVER CLOUD PLATFORM에 접속해 네이버 지도 Geocoding에 대한 Application 활용 등록으로 API 사용을 위한 ID와 Key 정보를 발급받는다.
[네이버 지도 Geocoding API key 발급 과정 참고 블로그]
https://dlagusgh1.tistory.com/987
2. 위경도 변환 코드 분석
requests.get() : 서버에 요청을 전달하고, 서버의 응답 결과 Response 객체를 반환
equest의 headers : 서버가 요청을 처리하기 위한 추가 정보를 제공
request의 params : 서버에 쿼리 매개변수를 전달
step 1. API에서 정보 받아오기
- header를 통해 네이버로부터 받은 인증을 위한 API key를 전달
- params를 통해 기본 url의 '?'뒤에 각 주소명 address가 붙은 주소변수로 전달
➡️ 각 주소마다 'url + 주소명'에 접근해서 json 형태로 위경도 정보를 받아온다.
step 2. 필요한 정보만 추출하기
- Response 객체의 데이터는 기본적으로 string(text) 형식으로 출력. string을 json 형식으로 변환하여 출력하기 위해 Response 객체.json() 실행해 받아온 데이터를 json 형식으로 변환 (dictionary 형태로 변환)
- 데이터 dictionary의 'addresses' 부분에서 'x'와 'y'만 추출
➡️ 각 주소마다 위도/경도 값만 추출한다.
※ 쿼리 스트링(Query String) 주소 표현
https://주소/주소?key2=value2&key1=value1
물음표 '?' 뒤에 나타나는 데이터를 쿼리 스트링이라 부르며 "?key=value"의 형식으로 데이터를 구분한다.
request는 매개변수 params을 통해 url 주소에서 '?' 이후에 들어갈 쿼리 변수를 전달한다.
예) 'https://www.google.com/search?q=검색어' url에서 '검색어' 부분이 쿼리 스트링에 해당한다.
import requests
def geocode(address, api_key):
#geocode 기본 url
base_url = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode"
#헤더로 API 정보 전달
headers = {
"X-NCP-APIGW-API-KEY-ID": api_key,
"X-NCP-APIGW-API-KEY": api_key}
#url ? 뒤에 각각의 주소 text 전달
#json 형식으로 데이터 받아오기
params = {
"query": address,
"output": "json"}
#데이터 요청
response = requests.get(base_url, headers=headers, params=params)
#json 형태로 변환
data = response.json()
if "addresses" in data:
if len(data["addresses"]) > 0:
latitude = data["addresses"][0]["y"]
longitude = data["addresses"][0]["x"]
return latitude, longitude, data
return None, None, None
Jupyter Notebook
build = pd.read_csv(path + '/데이터 전처리/지도기반 데이터/서울시 주요 공기업 리스트 정보 (한국어_2015년).csv', encoding='cp949').iloc[:, [4,5,7,8]]
build.head()
명칭 | 도로명 주소 | 행정 구 | 행정 동 | |
---|---|---|---|---|
0 | 한국데이터베이스진흥원 | 서울특별시 종로구 종로51 종로타워 19층 | 종로구 | 종로1.2.3.4가동 |
1 | 한국도박문제관리센터 | 서울특별시 종로구 북촌로 18 | 종로구 | 가회동 |
2 | 한국문학번역원 | 서울특별시 강남구 영동대로 112길 32(삼성동) | 강남구 | 삼성1동 |
3 | 한국문화관광연구원 | 서울특별시 강서구 금낭화로 154 | 강서구 | 방화3동 |
4 | 한국문화예술교육진흥원 | 서울시 마포구 성산로 128(성산동 275-3) | 마포구 | 성산1동 |
import requests
def geocode(address, api_key):
#geocode 기본 url
base_url = "https://naveropenapi.apigw.ntruss.com/map-geocode/v2/geocode"
#헤더로 API 정보 전달
headers = {
"X-NCP-APIGW-API-KEY-ID": api_key,
"X-NCP-APIGW-API-KEY": api_key}
#url ? 뒤에 각각의 주소 text 전달
#json 형식으로 데이터 받아오기
params = {
"query": address,
"output": "json"}
#데이터 요청
response = requests.get(base_url, headers=headers, params=params)
#json 형태로 변환
data = response.json()
if "addresses" in data:
if len(data["addresses"]) > 0:
latitude = data["addresses"][0]["y"]
longitude = data["addresses"][0]["x"]
return latitude, longitude, data
return None, None, None
위도_list =list() #위도 list
경도_list =list() #경도 list
json_data=[] #API 전체 data list
api_key = 'qTlsYMEbCnDMguYa6vVg50kUtOwvVq0LAmcc2gXb'
for address in build["도로명 주소"]:
address = address.split("(")[0]
latitude, longitude, data = geocode(address, api_key)
위도_list.append(latitude)
경도_list.append(longitude)
json_data.append(data)
print(f"{build.iloc[0,1]} => 주소 json으로 변환결과\n")
print(f'x 좌표: {json_data[0]["addresses"][0]["x"]}')
print(f'y 좌표: {json_data[0]["addresses"][0]["y"]}')
print(json_data[0]["addresses"][0])
서울특별시 종로구 종로51 종로타워 19층 => 주소 json으로 변환결과
x 좌표: 126.9836385
y 좌표: 37.5707534
{'roadAddress': '서울특별시 종로구 종로 51 종로타워', 'jibunAddress': '서울특별시 종로구 종로2가 6 종로타워', 'englishAddress': '51, Jong-ro, Jongno-gu, Seoul, Republic of Korea', 'addressElements': [{'types': ['SIDO'], 'longName': '서울특별시', 'shortName': '서울특별시', 'code': ''}, {'types': ['SIGUGUN'], 'longName': '종로구', 'shortName': '종로구', 'code': ''}, {'types': ['DONGMYUN'], 'longName': '종로2가', 'shortName': '종로2가', 'code': ''}, {'types': ['RI'], 'longName': '', 'shortName': '', 'code': ''}, {'types': ['ROAD_NAME'], 'longName': '종로', 'shortName': '종로', 'code': ''}, {'types': ['BUILDING_NUMBER'], 'longName': '51', 'shortName': '51', 'code': ''}, {'types': ['BUILDING_NAME'], 'longName': '종로타워', 'shortName': '종로타워', 'code': ''}, {'types': ['LAND_NUMBER'], 'longName': '6', 'shortName': '6', 'code': ''}, {'types': ['POSTAL_CODE'], 'longName': '03161', 'shortName': '03161', 'code': ''}], 'x': '126.9836385', 'y': '37.5707534', 'distance': 0.0}
build_df = pd.concat([build, pd.DataFrame({"위도" : 위도_list}), pd.DataFrame({"경도":경도_list})], axis=1)
build_df.head()
명칭 | 도로명 주소 | 행정 구 | 행정 동 | 위도 | 경도 | |
---|---|---|---|---|---|---|
0 | 한국데이터베이스진흥원 | 서울특별시 종로구 종로51 종로타워 19층 | 종로구 | 종로1.2.3.4가동 | 37.5707534 | 126.9836385 |
1 | 한국도박문제관리센터 | 서울특별시 종로구 북촌로 18 | 종로구 | 가회동 | 37.5784155 | 126.9858037 |
2 | 한국문학번역원 | 서울특별시 강남구 영동대로 112길 32(삼성동) | 강남구 | 삼성1동 | 37.5152350 | 127.0628625 |
3 | 한국문화관광연구원 | 서울특별시 강서구 금낭화로 154 | 강서구 | 방화3동 | 37.5791935 | 126.8138736 |
4 | 한국문화예술교육진흥원 | 서울시 마포구 성산로 128(성산동 275-3) | 마포구 | 성산1동 | 37.5637955 | 126.9082019 |
Reference
https://ko.wikipedia.org/wiki/%EC%A7%80%EC%98%A4%EC%BD%94%EB%94%A9
https://hotel-iu.tistory.com/303
https://dlagusgh1.tistory.com/987
https://hogni.tistory.com/33
https://velog.io/@kjyeon1101/API-Python-API-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B0%9B%EC%95%84%EC%98%A4%EA%B8%B0-JSON-%ED%8C%8C%EC%8B%B1%ED%95%98%EA%B8%B0
https://mixedanalytics.com/knowledge-base/api-headers-explained/https://mixedanalytics.com/knowledge-base/api-headers-explained/
'TAVE > 뿌스팅 project' 카테고리의 다른 글
[애플리케이션] streamlit 웹 구현 (0) | 2023.08.07 |
---|---|
[모델링] 예측 모델 모델링 및 성능 평가 (0) | 2023.08.07 |
[데이터 전처리] 설명변수 PCA (0) | 2023.08.07 |
[데이터 전처리] Encoding 인코딩 (0) | 2023.08.07 |
[데이터 전처리] EDA 및 변수 선택 (0) | 2023.08.07 |