강의영상

- (1/7) Map object (1)

- (2/7) Map object (2)

- (3/7) Marker (1)

- (4/7) Marker (2)

- (5/7) flugins (1)

- (6/7) flugins (2)

- (7/7) 지진자료시각화

import

import numpy as np 
import pandas as pd
import folium

folium.Map

- global view

m=folium.Map(scrollWheelZoom=False)
#m

- location과 scale을 조정하는 방법

m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=16)
#m

- tiles 옵션을 주어서 지도의 외형을 변경하여 보자.

  • "OpenStreetMap"
  • "Stamen Terrain", "Stamen Toner", "Stamen Watercolor"
  • "CartoDB positron", "CartoDB dark_matter"
m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=15,
             tiles="CartoDB positron")
#m

folium.Marker

- 지도위에 무엇인가 오브젝트를 추가하는데, 가장 기본적인 것이 마커임 (점이라 생각해도 괜찮음)

- 마커안에 내용을 넣을 수 있음. (경우에 따라서는 유용하다)

m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=14,
             tiles="CartoDB positron")
folium.Marker(location=[35.84676618432067, 127.12936405235232],
              #tooltip='Click me',
              popup='JBNU',
              icon=folium.Icon(color='red',icon='university',prefix='fa')
             ).add_to(m) 

folium.Marker(location=[35.837688889992634, 127.11212714586104],
              #tooltip='Click me',
              popup='HOME'              
             ).add_to(m) 
#m
<folium.map.Marker at 0x7f54727532b0>

- 조금 더 다양한 아이콘들을 추가하여 보자.

m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=14,
             tiles="CartoDB positron")
folium.Marker(location=[35.84676618432067, 127.12936405235232],
              #tooltip='Click me',
              popup='JBNU',
              icon=folium.Icon(color='red',icon='music',prefix='fa')
             ).add_to(m) 

folium.Marker(location=[35.837688889992634, 127.11212714586104],
              #tooltip='Click me',
              popup='HOME'              
             ).add_to(m) 
#m
<folium.map.Marker at 0x7f5472753790>

- icon='university' 대신에 쓸만한 옵션들

  • icon='street-view'
  • icon='tree'
  • icon='plane'
  • icon='bell'
  • ...

https://getbootstrap.com/docs/3.3/components/

- 마커에 HTML넣기

m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=14,
             tiles="CartoDB positron")
folium.Marker(location=[35.84676618432067, 127.12936405235232],
              #tooltip='Click me',
              popup='<h2> JBNU </h2><br>',
              icon=folium.Icon(color='red',icon='music',prefix='fa')
             ).add_to(m) 

folium.Marker(location=[35.837688889992634, 127.11212714586104],
              #tooltip='Click me',
              popup='<h5> HOME </h5><br>'              
             ).add_to(m) 
#m
<folium.map.Marker at 0x7f54a844e340>

- 마커에 DataFrame (을 HTML로 바꿔서) 넣기

df= pd.DataFrame(data=[[2019,35],[2020,35],[2021,33]],columns=['Year','Enrollment'])
df.to_html()
'<table border="1" class="dataframe">\n  <thead>\n    <tr style="text-align: right;">\n      <th></th>\n      <th>Year</th>\n      <th>Enrollment</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>2019</td>\n      <td>35</td>\n    </tr>\n    <tr>\n      <th>1</th>\n      <td>2020</td>\n      <td>35</td>\n    </tr>\n    <tr>\n      <th>2</th>\n      <td>2021</td>\n      <td>33</td>\n    </tr>\n  </tbody>\n</table>'
m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=14,
             tiles="CartoDB positron")
folium.Marker(location=[35.84676618432067, 127.12936405235232],
              #tooltip='Click me',
              popup='<h2> JBNU </h2><br>'+df.to_html(),
              icon=folium.Icon(color='red',icon='music',prefix='fa')
             ).add_to(m) 

folium.Marker(location=[35.837688889992634, 127.11212714586104],
              #tooltip='Click me',
              popup='<h5> HOME </h5><br>'              
             ).add_to(m) 
#m
<folium.map.Marker at 0x7f547270ef10>

- 논리구조상 HTML 오브젝트를 아무거나 넣을 수 있다. $\to$ 그림도 넣을 수 있나?

import base64
import matplotlib.pyplot as plt 
fig = plt.figure()
plt.plot([1,2,3,4],[2,3,4,3],'o--r')
fig.savefig('temp.png')
_encoded = base64.b64encode(open('temp.png','rb').read())
_myhtml = '<img src="data:image/png;base64,{}">'.format
_iframe = folium.IFrame(_myhtml(_encoded.decode('UTF-8')),width=400,height=300)
_popup = folium.Popup(_iframe)
  • 인터넷에서 긁어온 코드
m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=13,
             tiles="CartoDB positron"
            )
folium.Marker(location=[35.84676618432067, 127.12936405235232],
              #tooltip='Click me',
              popup=_popup,
              icon=folium.Icon(color='red',icon='music',prefix='fa')
             ).add_to(m) 

folium.Marker(location=[35.837688889992634, 127.11212714586104],
              #tooltip='Click me',
              popup='<h5> HOME </h5><br>'              
             ).add_to(m) 
#m
<folium.map.Marker at 0x7f5470a2b370>

folium.CircleMarker

m=folium.Map(scrollWheelZoom=False,
             location=[35.84676618432067, 127.12936405235232],
             zoom_start=13,
             tiles="CartoDB positron")
folium.Marker(location=[35.84676618432067, 127.12936405235232],
              #tooltip='Click me',
              popup=_popup,
              icon=folium.Icon(color='red',icon='music',prefix='fa')
             ).add_to(m) 

folium.CircleMarker(location=[35.84676618432067, 127.12936405235232], 
                    radius=40,
                    color=None,
                    fill=True,
                    fill_color='red',
                    popup='JBNU').add_to(m)

folium.Marker(location=[35.837688889992634, 127.11212714586104],
              #tooltip='Click me',
              popup='<h5> HOME </h5><br>'              
             ).add_to(m) 
#m
<folium.map.Marker at 0x7f5470a472b0>

- 다양한 마커를 그냥 지옴처럼 생각해도 괜찮아보임

- 동그라미 하나 그리는데 너무 많이 노력을 하는것 같기도 함.

- Circle이 아니라 라인, 사각형, 폴리곤등도 지도에 추가할수 있으나 더 많은 노력이 필요하다.

plugins.HeatMap

- Heatmap은 폴리움에서 데이터 시각화를 하기에 적합한 기본도구임

from folium import plugins 
data=(np.random.normal(size=(100,3)) + np.array([[28,77,5]])).tolist()
m=folium.Map([28,77],zoom_start=6,scrollWheelZoom=False)
plugins.HeatMap(data).add_to(m) 
#m
<folium.plugins.heat_map.HeatMap at 0x7f547270ee20>

plugins.HeatMapWithTime

- 입자의 위치

$$\begin{cases} x_t = x_{t-1} +\epsilon_t \\ y_t = y_{t-1} +\eta_t \end{cases}$$

단 $(x_0,y_0)=(35.837688889992634, 127.11212714586104)$ 라고 하고 $\epsilon_t$와 $\eta_t$는 서로 독립인 정규분포이다.

  • 최종적인 차원: 프레임수 점의수 2

step1: numpy

t0 = np.array([[35.837688889992634,127.11212714586104]]*3000)
walk = np.random.normal(size=(200,3000,2)) * 0.0001 
t0 # 시점0 
array([[ 35.83768889, 127.11212715],
       [ 35.83768889, 127.11212715],
       [ 35.83768889, 127.11212715],
       ...,
       [ 35.83768889, 127.11212715],
       [ 35.83768889, 127.11212715],
       [ 35.83768889, 127.11212715]])
t0+walk[0,:,:]# 시점1
array([[ 35.83755719, 127.11227851],
       [ 35.83765071, 127.11201433],
       [ 35.83789666, 127.11204495],
       ...,
       [ 35.83768979, 127.11199086],
       [ 35.83755687, 127.11218764],
       [ 35.83755343, 127.11213141]])
t0+walk[0,:,:]+walk[1,:,:]# 시점2
array([[ 35.83749504, 127.11210571],
       [ 35.83752415, 127.11207603],
       [ 35.83815204, 127.11198859],
       ...,
       [ 35.83775445, 127.11185324],
       [ 35.83749663, 127.11216901],
       [ 35.83735671, 127.11200109]])

- 그런데 walk[0,:,:]+walk[1,:,:]를 좀더 간단하게 쓸수 있다.

walk[0,:,:]+walk[1,:,:]
array([[-1.93853401e-04, -2.14362201e-05],
       [-1.64739936e-04, -5.11175119e-05],
       [ 4.63152733e-04, -1.38557716e-04],
       ...,
       [ 6.55632933e-05, -2.73901961e-04],
       [-1.92264443e-04,  4.18592999e-05],
       [-3.32182778e-04, -1.26051762e-04]])
walk[:2,:,:].sum(axis=0)
array([[-1.93853401e-04, -2.14362201e-05],
       [-1.64739936e-04, -5.11175119e-05],
       [ 4.63152733e-04, -1.38557716e-04],
       ...,
       [ 6.55632933e-05, -2.73901961e-04],
       [-1.92264443e-04,  4.18592999e-05],
       [-3.32182778e-04, -1.26051762e-04]])

- 따라서 시점2는 아래와 같이 표현가능

t0+walk[:2,:,:].sum(axis=0)
array([[ 35.83749504, 127.11210571],
       [ 35.83752415, 127.11207603],
       [ 35.83815204, 127.11198859],
       ...,
       [ 35.83775445, 127.11185324],
       [ 35.83749663, 127.11216901],
       [ 35.83735671, 127.11200109]])

- 그렇다면 시점3은?

t0+walk[:3,:,:].sum(axis=0)
array([[ 35.83746132, 127.11195158],
       [ 35.83740523, 127.11208138],
       [ 35.83810142, 127.11186624],
       ...,
       [ 35.83767941, 127.1118255 ],
       [ 35.83733062, 127.11206738],
       [ 35.83743684, 127.11198322]])

- 따라서 data 는

data = [(t0+walk[:i,:,:].sum(axis=0)).tolist() for i in range(200)]
np.array(data).shape
(200, 3000, 2)

- 이제 data[0], data[1], data[2], ... data[199]까지 대입하여 각각 그림을 그리고 시각화하면 된다.

step2: folium

m=folium.Map(scrollWheelZoom=False,
             location=[35.837688889992634,127.11212714586104],
             zoom_start=16)
plugins.HeatMapWithTime(data,radius=5).add_to(m)
#m
<folium.plugins.heat_map_withtime.HeatMapWithTime at 0x7f547270e280>
  • 가스의 확산과정

예제: earthquakes

Step1: Pandas

df=pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/earthquakes-23k.csv')
df
Date Latitude Longitude Magnitude
0 01/02/1965 19.2460 145.6160 6.0
1 01/04/1965 1.8630 127.3520 5.8
2 01/05/1965 -20.5790 -173.9720 6.2
3 01/08/1965 -59.0760 -23.5570 5.8
4 01/09/1965 11.9380 126.4270 5.8
... ... ... ... ...
23407 12/28/2016 38.3917 -118.8941 5.6
23408 12/28/2016 38.3777 -118.8957 5.5
23409 12/28/2016 36.9179 140.4262 5.9
23410 12/29/2016 -9.0283 118.6639 6.3
23411 12/30/2016 37.3973 141.4103 5.5

23412 rows × 4 columns

lst=[df.assign(Year=list(map(lambda x: x.split('/')[-1], df.Date))).\
groupby('Year').\
pipe(list)[i][1].iloc[:,[1,2,3]].\
to_numpy().tolist() for i in range(2017-1965)]

Step2: folium

m=folium.Map(scrollWheelZoom=False)
plugins.HeatMapWithTime(lst,radius=5,index=list(range(1965,2017))).add_to(m)
#m
<folium.plugins.heat_map_withtime.HeatMapWithTime at 0x7f5472755d60>

- 숙제:

지진자료에서 1985년 이후의 자료만 고른뒤에 HeatMapWithTime()을 이용하여 시각화하라.