데이터분석/미니프로젝트 01. 서울시 CCTV 현황 분석

미니프로젝트 01-02-06. Folium 지도 시각화

책다니엘 2024. 3. 29. 17:30

1. 이번에는 지도시각화를 하는 도구 중에 가장 유명한 도구 중 하나인 Folium을 다뤄볼 것이다. 데이터사이언스에서 지도시각화 자체를 많이 사용하지는 않지만, 이번 프로젝트에서 서울시 구별 범죄 시각화를 위해 필요한 만큼만 활용하기로 한다.

import Folium

 

지도시각화 도구는 많지만, 사용의 편의성이나 활발한 기능 개선 등으로 인해 Folium이 만족도가 높은 편이라고 한다. (2017년 정도 기준, 현재는 더 많은 지도시각화 프로그램이 있을 것이다. 최근에는 카카오맵 API 등도 매우 접근성이 높고 성능도 좋다) Folium은 Chrome환경에서 가장 동작이 잘 된다.

 

2. 먼저 conda 프롬프트에서 conda install conda-forge::folium 명령어로 folium을 설치해주자.

 

3. folium.map([위도, 경도]) 명령어로 지도를 표시해주자.

* explorer, edge, whale 등에서는 잘 안 된다.

드래그 앤 드랍으로 지도 확대/축소, 이동도 가능하다. 심지어 엄청 빠르다!

4. 지도를 html파일로 저장 가능하다.

m.save('../data/index.html')

 

5. 스타일을 tiles옵션으로 지정 가능하다. 

folium.Map(location=[45.5236, -122.6750], tiles='Stamen Toner', zoom_start=13)

!!주의!!

위의 코드를 실행하면 아무것도 뜨지 않는다. 일단 folium에서 제공해주는 tiles목록을 확인해봤다. 

https://python-visualization.github.io/folium/latest/user_guide/raster_layers/tiles.html#Other-tilesets

 

Tiles — Folium 0.1.dev1+g12b8807 documentation

Make this Notebook Trusted to load map: File -> Trust Notebook

python-visualization.github.io

기본적으로 제공해주는(Built-in) 타일셋은 총 세개였다. OpenStreetMap, Cartodb Positron, Cartodb dark-matter이다. 그러나 이번 강의에서 사용하는 지도는 Stamen스타일의 흑백 타일이다. Stamen 타일셋을 제공해주는 페이지에 들어가 확인해보았다.

https://docs.stadiamaps.com/guides/migrating-from-stamen-map-tiles/

 

Migration Guide for Stamen Map Tile Users - Stadia Maps Documentation

Welcome Stamen map tile users! Stamen's iconic styles are now hosted by Stadia Maps. Here's what you need to know.

docs.stadiamaps.com

가입을 한 다음, api키를 받아 xyzprovider를 이용하여 불러오라고 한다. xyzprovider는 conda install conda-forge::xyzproviders명령어로 설치했다. 제공해주는 코드를 기초로 api키를 받아 코드를 작성하면 이렇다.

import folium
import xyzservices.providers as xyz

m = folium.Map(location=[39.7684, -86.1581], zoom_start=12)

#Add the Stadia Maps Stamen Toner provider details via xyzservices
tile_provider = xyz.Stadia.StamenToner

#Update the URL to include the API key placeholder
tile_provider["url"] = tile_provider["url"] + "?api_key={api_key}"

#Create the folium TileLayer, specifying the API key
folium.TileLayer(
    tiles=tile_provider.build_url(api_key='api_key'), # api키 여기에 입력
    attr=tile_provider.attribution,
    name=tile_provider.name,
    max_zoom=tile_provider.max_zoom,
    detect_retina=True
).add_to(m)

folium.LayerControl().add_to(m)
m

오른쪽 상단 버튼으로 openStreetMap과 Stamen Toner 옵션을 선택할 수 있다.

정상적으로 출력된다!

 

6. 그 다음엔 지도에 마커를 찍어 보자. 이번엔 stamen_terrain이라는 타일을 사용한다. 구글링을 해서 더 편한 방식의 코드를 찾아서 적용해보았다.

tiles = "https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.png?api_key=API키 여기에 입력"
attr = "terrain"

my_map = folium.Map(
    location=[45.372, -121.6972],
    zoom_start=12,
    tiles=tiles,
    attr=attr
)
folium.Marker([45.3288,-121.6625], popup="<i>Mt. Hood Meadows</i>").add_to(my_map)
folium.Marker([45.3311,-121.7113], popup="<b>Timberline Lodge</b>").add_to(my_map)

my_map

 

마커가 정상적으로 표시되며, 마커를 누르면 내가 입력한 정보가 나타난다. <i>는 이탤릭체, <b>는 볼드체

7. 더 다양한 마커를 사용해보자.

tiles = "https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.png?api_key=API키 여기에 입력"
attr = "terrain"

my_map = folium.Map(
    location=[45.372, -121.6972],
    zoom_start=12,
    tiles=tiles,
    attr=attr
)
folium.Marker([45.3288,-121.6625], popup="<i>Mt. Hood Meadows</i>", icon=folium.Icon(icon="cloud"),).add_to(my_map)
folium.Marker([45.3311,-121.7113], popup="<b>Timberline Lodge</b>", icon=folium.Icon(color="green"),).add_to(my_map)
folium.Marker([45.3300,-121.6823], popup="한글테스트", icon=folium.Icon(color="red", icon='info-sign'),).add_to(my_map)

my_map

 

8. folium의 Circle기능과 CircleMarker기능도 사용해보자.

tiles = "https://tiles.stadiamaps.com/tiles/stamen_toner/{z}/{x}/{y}{r}.png?api_key=API키 여기에 입력"
attr = "toner"

my_map = folium.Map(
    location=[45.5236, -122.6750],
    zoom_start=13,
    tiles=tiles,
    attr=attr
)
folium.Circle(
    radius=100,
    location=[45.5244, -122.6699],
    popup='The WaterFront',
    color='crimson',
    fill=False,
).add_to(my_map)
folium.CircleMarker(
    radius=50,
    location=[45.5215, -122.6261],
    popup='Laurelhurst Park',
    color='#3186cc',
    fill=True,
    fill_color='#3186cc',
).add_to(my_map)

my_map

 

9. 클릭했을 때 위도 경도 정보를 반환하게 할 수도 있다.

tiles = "https://tiles.stadiamaps.com/tiles/stamen_terrain/{z}/{x}/{y}{r}.png?api_key=API키 여기에 입력"
attr = "terrain"

my_map = folium.Map(
    location=[46.1991, -122.1889],
    zoom_start=13,
    tiles=tiles,
    attr=attr
)
my_map.add_child(folium.LatLngPopup())
my_map

신기해라!

 

10. 이번 강의에서는 수업자료로 미국의 각 주마다 id와 위도,경도가 표시되어있는 json파일을 나눠주었다. 파일을 보면 각 주의 경계선과 id가 구현되어있다.

 

11. 또한 이와 매칭되는 id값을 가지는 csv파일도 나눠주었다.

12. 이를 아래와 같은 방식으로 불러올 수 있다.

import json

state_data = pd.read_csv('../data/02. US_Unemployment_Oct2012.csv')

m = folium.Map(
    location = [48,-102],
    zoom_start = 3
)
folium.Choropleth(
    geo_data='../data/02. us-states.json',
    data=state_data,
    columns = ['State', 'Unemployment'],
    key_on = 'feature.id',
    fill_color='YlGn',
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name='Unemployment Rate(%)',
).add_to(m)
m

folium.Choropleth() 기능은 경계선을 따라 하나의 덩어리로 잡고, 각 덩어리마다 색상을 입힐 수 있다. 경계선 데이터는 geo_data가 되고, data변수에 들어온 state_data는 'State'와 'Unemployment' 컬럼으로 되어 있다고 지정해준다. 마지막으로 이것들을 add_to()메서드로 m(지도)변수에 넣어주면 아래와 같은 지도가 나온다.