본문 바로가기

study

Mapbox를 활용한 지역별 코로나 감염자 시각화

Reference - https://dailyheumsi.tistory.com/145?category=854906 

공간정보 시각화 라이브러리 중에 가장 직관적이며 시각적으로 매력적이다. 정리가 잘 되어 있는 블로그가 있어 참고했다. 파이썬에서 사용가능한 라이브러리도 있고 마침 구별 경계 json파일이 있어 코로나 이슈에 맞게 활용해보았다. (내가 가진 geojson 파일은 행정동이라 블로그에서 사용한 데이터를 활용했다.) 

 

1. 데이터 수집 
2. 데이터 가공
3. 시각화

 

1. 데이터 수집

import urllib.request
url = "http://www.seoul.go.kr/coronaV/coronaStatus.do#status_page_top"
page = urllib.request.urlopen(url)
page = page.read() 

서울시 코로나19 페이지의 확진자 현황 내용 크롤링

 

BeautifulSoup을 활용하여 데이터를 가져온다.

from bs4 import BeautifulSoup
soup = BeautifulSoup(page,'html.parser')

seoul_gu = soup.find_all('h5',"update-date")[1]
corona_gu_total = seoul_gu.get_text()
corona_gu_total = corona_gu_total.split('(')[1]
corona_gu_total = corona_gu_total.split()[0:25]
corona_gu_total

구 + 확진자 수

 

2. 데이터 가공

구별 확진자 수를 판다스 형태로 정리한다.

import pandas as pd

corona_df = pd.DataFrame(corona_gu_total)
corona_df = corona_df.rename(columns={0 : "seoul_gu"})

# 구와 확진자수 구분
corona_df["num_corona"] = corona_df["seoul_gu"].str.extract('(\d+)')
corona_df["seoul_gu"] = corona_df["seoul_gu"].str.extract('(\D+)')

# 중구의 경우 애초에 '중구'라고 명시되어 있음
corona_df["seoul_gu"] = corona_df["seoul_gu"] + '구'
corona_df["seoul_gu"][23] = '중구'

최종 구별 확진자 수

 

지도에 구별로 시각화하기 위해서는 구별 경계를 나누는 공간정보가 필요하다. 서울의 행정구 경계 데이터는 국가공간정보포털과 공공데이터 포털을 통해 다운 받을 수 있다.

# 구별 경계선 json 파일
import json
geo_data = "C:/Users/kjh96/Github/Study_Geodata/seoul_gu.json"

with open(geo_data,encoding="utf-8") as f:
    data = json.loads(f.read())

json형태의 구 경계 데이터

 

data의 name 값과 corona_df의 seoul_gu 값이 일치할 경우 data의 features값 안에 확진자 수 데이터를 삽입해준다.

# 행정구역 경계에 구별 코로나 감염자 수 추가
for i in range(len(corona_df)) : 
    for j in range(len(corona_df)) : 
        if data['features'][i]['properties']["name"] == corona_df["seoul_gu"][j] : 
            data['features'][i]['properties']["corona"] = int(corona_df["num_corona"][j])

위의 기존의 json파일에 'corona' 값이 추가된 것을 확인할 수 있다.

 

3. 시각화

입체적인 느낌을 살리기 위해 지도를 사방으로 기울여 3D 형태로 시각화했다.

from mapboxgl.viz import *
from mapboxgl.utils import create_color_stops 
from mapboxgl.utils import create_numeric_stops
import mapboxgl

# 토큰 
token = 'pk.eyJ1IjoiZHVjazk2NjciLCJhIjoiY2thNzRiMXhxMGQ5NTJ0cXB0dGpmZ3RrOSJ9.f45On_lrv6Nm4iO7oCg7nw'

# 서울시 중심부의 경도, 위도 입니다. 
center = [126.986, 37.565] 

# 시각화 할 값에 따른 색상의 범주를 지정해줍니다. 
color_breaks = [0, 10, 20, 30, 40, 50] 
color_stops = create_color_stops(color_breaks, colors='BuPu')

# ChoroplethViz 를 그립니다.
viz = ChoroplethViz(access_token=token, data=data, color_property='corona', color_stops=color_stops, center=center, zoom=10)

# 맵을 -15도 만큼 좌우 회전하고, 45도 만큼 상하 회전합니다. 
viz.bearing = -15
viz.pitch = 45

# 각 데이터에 '인구'를 기준으로 height 값을 줍니다.
viz.height_property = 'corona'

# 높이의 값을 '인구' 에 따라 아래 간격으로 매핑합니다.
numeric_stops = create_numeric_stops([0, 10, 20, 30, 40, 50], 0, 3000)

viz.height_stops = numeric_stops
viz.height_function_type = 'interpolate'

# 맵을 출력합니다. 
viz.show()

 

결론

경계 데이터를 활용하여 특정 구역을 시각화하는 방법은 매우 매력적인 방법이다. 보는 사람으로 하여금 직관적으로 이해하게 하며 시각적으로도 근사하다. 특히 Mapbox를 활용할 경우 더욱 그러하다. 아이디어가 생기면 다른 스타일로 만들어 봐야겠다.

 

  • 소비 2020.08.14 00:38

    안녕하세요 데이터 시각화에 관심이 있는 학생입니다! 저도 지금 mapbox를 이용해서 좀더 이쁜 데이터 시각화를 해보고 싶어서 이렇게 찾아오게 됐습니다 ! 혹시 서울 구별 geojson은 어디에서 구할 수 있는지 알 수 있을까여?? 아무리 찾아도 보이지가 않네요 ㅠㅠ :)