티스토리 뷰
목적
지도 위에 우편 번호를 표시합니다.
folium을 이용한 지도 위 우편번호 표시
데이터 준비
1. 권역코드-우편번호 csv파일(code-bas_id_euc-kr.csv)
파일다운로드: 지리 데이터 시각화(4) - folium으로 명목형 choropleth 지도 그리기, tool tip 사용
2. 서울시 기초 구역도 geo json파일(TL_KODIS_BAS_W.json)
파일다운로드: 지리 데이터 시각화(2) - 좌표계 변경 (UTM-K -> WGS84), GeoJSON
colab에서 작업을 하였습니다.
위에서 만든 두 파일을 불러옵니다.
필요한 라이브러리를 import 합니다.
import folium
from folium import plugins
import pandas as pd
import matplotlib.colors as mcolors
import json
첫 번째 파일인 권역코드-우편번호 csv 파일을 읽어 df라는 변수에 대입하고,
우편번호를 전처리(zfill)하고,
컬럼명을 변경('우편번호*'->'BAS_ID', '권역코드*'->'CD)합니다.
df = pd.read_csv('sample_data/code-bas_id_euc-kr.csv', encoding = 'euc-kr')
df['우편번호*'] = df['우편번호*'].astype('str').str.zfill(5) # 다섯자리 맞춰주기 위해.
df.rename(columns={'우편번호*':'BAS_ID'}, inplace=True)
df.rename(columns={'권역코드*':'CD'}, inplace=True)
df.head()
두 번째 파일인 서울 geo json 파일을 가져와 geo_json이라는 변수에 대입합니다.
# 서울 geo json 가져오기
with open('sample_data/TL_KODIS_BAS_W.json') as response:
geo_json = json.load(response)
geo_json의 properties에 df에 있는 권역코드('CD')정보 추가
이제 geo_json에 df에 있는 정보를 합쳐보도록 하겠습니다.
geo_json 데이터의 ['properties']에 'AREA_CD'라는 키를 추가해 해당 우편번호의 권역 코드('CD') 값을 df에서 가져와 채웁니다.
df['BAS_ID']에 해당 우편번호가 없다면 AREA_CD엔 'None'값을 채웁니다.
for i in range(len(geo_json['features'])):
try:
area_cd = df[df['BAS_ID'] == geo_json['features'][i]['properties']['BAS_ID']]['CD'].tolist()[0]
geo_json['features'][i]['properties']['AREA_CD'] = area_cd
except:
geo_json['features'][i]['properties']['AREA_CD'] = 'None'
(try except 구문은 안 쓰는 게 좋긴하지만ㅎㅎㅎ 이 데이터 상에서는 전혀 문제 없으니까 그냥 진행 할게요...ㅎㅎ 좋은 대안 있으신 분은 댓글주세요! 감사합니다.)
geo_json에서 AREA_CD가 None인 데이터는 불필요하니 제외하겠습니다.
new_geo_json = dict()
new_geo_json['type'] = geo_json['type']
new_geo_json['features'] = list()
# geo_json 에서 AREA_CD가 None인 데이터 제외
for i in range(len(geo_json['features'])):
if geo_json['features'][i]['properties']['AREA_CD'] == 'None':
continue
else:
new_geo_json['features'].append(geo_json['features'][i])
geo_json = new_geo_json
특정 권역('CD')에 해당하는 데이터만 선택하고 싶을 경우 아래와 같은 코드를 추가합니다. (저는 추가했습니다. )
# S12, S14인 데이터만 선택
new_geo_json = dict()
new_geo_json['type'] = geo_json['type']
new_geo_json['features'] = list()
for i in range(len(geo_json['features'])):
if geo_json['features'][i]['properties']['AREA_CD'].upper() == 'S12':
new_geo_json['features'].append(geo_json['features'][i])
elif geo_json['features'][i]['properties']['AREA_CD'].upper() == 'S14':
new_geo_json['features'].append(geo_json['features'][i])
else:
continue
geo_json = new_geo_json
지도 생성 및 색상 지정
저는 S12 권역이든 K12 권역이든 12권역이면 전부 orange색으로 칠하고,
S14든 K14든 14권역이면 전부 blue색으로 칠하려고 AREA_CD[1:]=='12', AREA_CD[1:]=='14' 조건을 넣었습니다.
(색상을 조금 더 쉽게 설정하는 방법: 지리 데이터 시각화(6) 의 color 참고)
center = [37.541, 126.986]
m = folium.Map(location=center, zoom_start=10)
def style_function(feature):
AREA_CD = feature['properties']['AREA_CD']
return {
'fillOpacity': 0.5,
'line_color' : 'black',
'weight': 0.5,
'fillColor': 'orange' if AREA_CD[1:] == '12' \
else 'blue'if AREA_CD[1:] == '14'\
else 'white'
}
gjson = folium.GeoJson(geo_json,
style_function=style_function,
).add_to(m)
우편번호 표시
get_loc 이라는 함수를 만들어 해당 우편번호의 중간 위, 경도를 구해 우편 번호를 중간에 적음.
(get_loc라는 함수를 만든 이유는 coordinates 값이 [[경도, 위도], [경도, 위도], ..., [경도, 위도]] 이런식으로 해당 우편번호의 경계마다 찍혀 있는데 경도의 평균 (avg_a), 위도의 평균(avg_b)값을 구해 해당 우편번호의 중간 위, 경도를 찾기 위해.)
def get_loc(coor):
avg_a = 0
avg_b = 0
for i in range(len(coor)):
avg_a += float(coor[i][0])
avg_b += float(coor[i][1])
avg_a = avg_a/len(coor)
avg_b = avg_b/len(coor)
return avg_b, avg_a
for i in range (len(new_geo_json['features'])):
folium.Marker(
location=get_loc(geo_json['features'][i]['geometry']['coordinates'][0]),
icon=plugins.BeautifyIcon(icon="arrow-down",icon_shape="circle", border_width=0, number=int(geo_json['features'][i]['properties']['BAS_ID']))
).add_to(m)
이렇게 지도 위에서 우편번호와 해당 우편번호가 커버하는 지역을 확인할 수 있습니다.
한 가지 아쉬운 점이 있다면 folium.Marker에서 icon에 대한 값을 줄 때 BeautifyIcon이라는 플러그인을 이용해서 줬는데
이 때 마커 위엔 숫자만 넣을 수 있고 텍스트는 못 넣더라구요. 그래서 우편번호 앞에 있던 0이 전부 잘리고 네자리만 보이네요.
'지리데이터시각화(geo)' 카테고리의 다른 글
지리 데이터 시각화 (6) folium을 이용한 경유지&경유 순서 시각화, marker의 icon 안에 숫자 (0) | 2022.03.06 |
---|---|
지리 데이터 시각화(5)- folium의 Choropleth지도 오류 (shape file) (0) | 2022.03.05 |
지리 데이터 시각화(4) - folium으로 명목형 choropleth 지도 그리기, tool tip 사용 (0) | 2022.03.05 |
지리 데이터 시각화(3) - plotly로 choropleth 지도 그리기 (Geo JSON, Geo Data Frame) (0) | 2022.03.05 |
지리 데이터 시각화(2) - 좌표계 변경 (UTM-K -> WGS84), GeoJSON (0) | 2022.03.05 |
- Total
- Today
- Yesterday