9. 지도 시각화(folium 패키지)

🔗 'Do it! 쉽게 배우는 파이썬 데이터 분석' 책을 기반으로 JupyterLab 환경에서 학습한 내용입니다 _φ(๑╹╹๑)

 

📌 지도 시각화 준비


  • folium 패키지 설치: 아나콘다 프롬프트에 pip install folium 작성

 

 

 

📌 시군구별 인구 단계 구분도


  • 시군구 경계 지도 데이터 불러오기
    1. open(): 파일 열기
    2. load(): 내용 불러오기
import json

# 시군구 경계 지도 데이터 불러오기
geo = json.load(open('SIG.geojson', encoding = 'UTF-8'))

"""
1. geojson: 위치 정보를 json 포맷으로 저장한 표준 지리 정보 데이터 포맷
2. SIG.geojson 파일 구조: 'features' 값에 각각의 시군구 정보가 딕셔너리 형태로 각각의 리스트에 포함되어 있음
{'features': [
{'type': 타입명,
'properties': {'SIG_CD': 행정구역코드, ...},
'geometry': {'type': 타입명, 'coordinates': [[[]]]
},
"""
# 첫 번째 행정 구역 코드 출력
geo['features'][0]['properties']

# 첫 번째 행정 구역 위도 경도 좌표 출력
geo['features'][0]['geometry']

 

  • 시군구별 인구 데이터 불러오기
import pandas as pd

# 시군구별 인구 데이터 불러오기
df_pop = pd.read_csv('Population_SIG.csv')
df_pop.head()

# 변수 속성 출력
df_pop.info()

# 숫자 형태의 행정 구역 코드 → 문자 형태로 변환 (geo 데이터의 행정 구역 코드와 형태 통일)
# 이름이 아니라 행정 구역 코드를 쓰는 이유: 이름은 중복될 수 있음
df_pop['code'] = df_pop['code'].astype(str)

 

  • 배경 지도 생성: folium 패키지의 Map(location = [지도 중심 위도, 지도 중심 경도], zoom_start = 확대할 정도, tiles = '지도 종류') 함수 활용
import folium

# 밝은 배경 지도 생성
# 밝은 배경의 지도를 생성하는 이유: 단계 구분이 잘 보이게 하기 위해
map_sig = folium.Map(location = [35.95, 127.7],
          zoom_start = 6.8,
          width = '90%',
          height = '100%',
          tiles = 'cartodbpositron')
map_sig

 

  • 단계 구분도 생성
    1. 계급 구간 설정: 경우에 따라 생략이 가능하며, 데이터프레임의 quantile() 함수를 활용하여 구간을 설정하고 리스트로 반환
    2. 단계 구분도 생성: folium 패키지의 Choropleth() 함수를 활용하며, geo_data를 기준으로 data를 결합하여 색상 레이어를 만드는 과정
      • geo_data = 지도 데이터명
      • data = 색으로 표현할 통계 데이터명
      • columns = ('지도 데이터와 연결할 통계 데이터의 변수명', '색으로 표현할 변수명')
      • key_on = '통계 데이터와 연결할 지도 데이터의 변수명'
        • feature로 시작하는 이유: 지도 데이터 geojson 파일에서 features을 사용하기로 약속되어 있고, features내에서 각 지역을 feature로 가져오게 설정되어 있다.
      • fill_color = '컬러맵명'
      • fill_opacity = 투명도
      • line_opacity = 경계선 투명도
      • bins =  계급 구간 변수명
    3. 배경 지도에 단계 구분도 추가: add_to(배경 지도명) 함수 활용
# 5개의 계급 구간 설정
# 구간을 설정해야 하는 이유: 경기도와 서울특별시의 인구가 다른 지역에 비해 극단적으로 커서 모든 지역이 동일한 색으로 표현
# 극단적으로 값이 크다는 것을 확인하는 방법: 상자 그림 등
# 구간 설정 이전에 서울이 다른 색으로 표현되지 않는 이유: 지도 데이터에서 서울특별시 내의 구단위로 나누어서 경계를 구성

bins = list(df_pop['pop'].quantile([0, 0.2, 0.4, 0.6, 0.8, 1]))
# 배경 지도에 단계 구분도 생성
folium.Choropleth(geo_data = geo,
data = df_pop,
columns = ('code', 'pop')
key_on = 'feature.properties.SIG_CD',
fill_color = 'YlGnBu',
fill_opacity = 1,
line_opacity = 0.5,
bins = bins)\
.add_to(map_sig)

map_sig

 

 

 

📌 서울시 동별 외국인 인구 단계 구분도


  • 서울시 동 경계 지도 데이터 불러오기
geo_seoul = json.load(open('EMD_Seoul.geojson', encoding = 'UTF-8'))
geo_seoul

 

  • 서울시 동별 외국인 인구 데이터 불러오기
foreigner = pd.read_csv('Foreigner_EMD_Seoul.csv')
foreigner.head()

# 변수 속성 출력
foreigner.info()

# 숫자 형태의 행정 구역 코드 → 문자 형태로 변환 (geo 데이터의 행정 구역 코드와 형태 통일)
foreigner['code'] = foreigner['code'].astype(str)

 

  • 배경 지도 생성
import folium

map_seoul = folium.Map(location = [37.56, 127],
                    zoom_start = 11,
                    tiles = 'cartodbpositron')

map_seoul

 

  • 단계 구분도 생성
# 8개 계급 구간 설정 (결측치 자동으로 제외)
bins = list(foreigner['pop'].quantile([0, 0.2, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]))

# 배경 지도에 단계 구분도 생성
# nan_fill_color: 결측치 지역 색깔 (foreigner['pop'].describe() 결과 최소값 7이므로 결측치는 외국인 존재 x 혹은 누락을 의미)
folium.Choropleth(geo_data = geo_seoul,
                 data = foreigner,
                 columns = ('code','pop'),
                 key_on = 'feature.properties.ADM_DR_CD',
                 fill_color = 'Blues',
                 nan_fill_color = 'White',
                 fill_opacity = 1,
                 line_opacity = 0.5,
                 bins = bins)\
.add_to(map_seoul)

map_seoul

 

  • 구 경계선 추가
# 구 경계 좌표 불러오기
geo_seoul_sig = json.load(open('SIG_Seoul.geojson', encoding = 'UTF-8'))

# 서울 구 라인 추가
# line_weight: 선 두께
folium.Choropleth(geo_data = geo_seoul_sig,
                 fill_opacity = 0,
                 line_weight = 4)\
.add_to(map_seoul)
map_seoul

 

  • 지도 저장: save('파일명') 함수를 활용하며, 웹 브라우저만 있으면 열어볼 수 있다.
map_seoul.save('map_seoul.html')