(11주차) 11월22일
카이로의 The Functional Art, folium
Cairo, A. Functional Art, The: An Introduction to Information Graphics and Visualization, New Riders, 2012. San Francisco, US.
-
((일반적생각, 카이로의 생각), 제 생각)으로 나누어서 설명
-
프리젠테이션방식의 시각화는 화자가 다듬은 이야기를 전달하기에 좋은 시각화이다. 즉 잘 정리된 메시지를 전달하기에 좋다.
- 문학적유기체라는 작품이다.
- 어떤 소설책을 시각화.
- 수형도 + 칼라
- 수형도의 의미: 단원, 문단, 문장, 단어 (수형도 계층적 구조를 시각화 하기에 뛰어남. ex: 리그레션트리!)
- 색깔: 여행, 음악, 파티 등 소설에서 자주 등장하는 소재 (색은 범주형 변수를 표현하기에 뛰어남)
-
익스플로래이션 방식은 독자가 스스로 그림에서 메시지를 찾아낸다.
-
소설을 읽어보지 않은 사람: 이 그래픽으로 소설책의 전체 주제를 미리 파악가능
-
소설을 이미 읽어본 사람: 분석 & 탐구를 할 수 있음. ex: 파티와 음악이 동시에 등장하는 경우가 많다.
-
카이로: 사실 프리젠테이션과 익스플로레이션은 절충가능함
- aes(x='GDP',y='불평등',text='년도',color='정부')
- 초록색정부: 소득이 증가 & 불평등이 훨씬 더 증가
- 갈색정부: 매우 빠른 경제 성장
- 포인트간의 간격이 조밀하다 = 변화가 더디다 // 포인트간의 간격이 넓다 = 변화가 빠르다.
-
언뜻보기에는 우리에게 익숙한 라인플랏인듯 보이지만 의외로 정보를 해석할만한 요소가 있다.
익스플로레이션형의 그래프는 그릴줄도 알아야 하지만 남이 그린 그래프를 해석할 수도 있어야함.
-
둘다 틀렸다.
-
가난한 나라의 출산율은 점점 감소
-
잘사는 나라의 출산율은 점점 증가
-
결국 세계의 인구는 안정화 될 것 (증가하지도 감소하지도 않는다)
-
아래의 그림이 그 증거이다.
-
리들러의 메시지는 아래의 그림들이 더 잘 전달한다.
-
어떠한 현상을 살펴볼때 그것의 부분집합들이 역시 그러한지 살펴보는것은 기본임
-
중요한 선을 제외한 나머지는 회색처리(일러스트레이터 사용) 한 것이 시각적으로 우수하며, 인상적이었음
-
과학적인 논문작업에 들어갈 그림이라면 임의로 회색처리한 것이 다소 비판을 받을 수 있음.
- Left: aes(x='출산율', y='수입')
- Right: aes(x='출산율', y='전체 중학생중 여학생이 차지하는 비율')
-
해설: 당신이 부자가 될수록 당신은 더 적은 아이를 가질 것이다. 중학교에 진학하는 여성이 적을수록 아이를 많이 낳는다. (그림밑에 주석을 해석)
-
여학생들을 중학교에 보내지 않으면 출산율이 올라가나요???
-
아래는 남미국가들의 국방력을 시각화한 그림
- 쓸모없는 그래픽
- 뭐 기억나는 것이 있나요?
-
아래가 더 우수한 그림이다. 더 정확한 비교를 할 수 있어요.
-
그리고 위의 그림보다 아래의 그림이 더 우수한 시각화이다.
- 일단 하이라이팅이 우아하네요.. (제가 시험문제 잘못낸 것 같아요)
- 브라질이 국방력도 우수하고 예산도 많이 투자하는 것 같지만 인구가 흑막인것 같다.
-
흑막을 제거
-
최종적으로 제안하는 그래프
- 좌측하단: aes(x='인구', y='군인수', size='예산')
- 우측하단: 관심있는 그래프가 아님
-
1사분면의 의미: 인구도 높고 군인수도 많은 나라 (똑같은 정보임 의미가 없다. 마치 x축이 토익점수, y축이 텝스점수 같은느낌임)
- 모든 점들이 직선에 몰려있다면? $\to$ 왜 2차원으로 표현함?
-
저같으면 aes(x='예산(인구효과제거)', y='군인수(인구효과제거)',size='인구')로 할것 같아요.
- 1사분면의 의미: 예산도 많이 쓰고 군인수도 많은나라 = 콜롬비아.
- 4사분면의 의미: 예산은 많이 쓰는데 군인수가 적은나라 = 브라질
-
산점도에서 데이터를 한눈에 파악하고 특징을 요약하기 위해서는 X,Y를 너무 비슷한 성질의 변수로 설정하지마라.
아래중 어떤것이 더 바람직한 그래프인가?
- aes(x='토익', y='텝스', color='합/불', shape='회사의종류')
- aes(x='토익', y='GPA', color='합/불', shape='회사의종류')
- 명암으로 왜 크기비교를 하는것인가?
-
비교를 위해서는 바플랏이 더 우수하다.
-
카이로교수님의 강의자료에 등장하는 그림
-
회색이 befor, 검은색이 after
- 크기비교는 바플랏으로 하는것이 아니다.
-
우리눈은 작원원이 큰원의 절반정도 차지한다고 느껴진다.
-
그렇지만 실제로는 아래와 같음
-
버블차트는 크기를 왜곡시킨다.
-
하지만 아래의 버블차트는 우수하다.
-
선거지도는 수치비교에 별로 관심이 없다.
-
대신에 민주당표와 공화당표가 어떤 지역에 몰렸는지 파악하는 것이중요
-
따라서 aes중 가장 중요한 x,y를 모두 지역에 투자함
-
시간경과에 따른 변화를 보여주고 싶으면 라인플랏, 비교를 하고 싶다면 바플랏, 관계를 알고싶다면 산점도.
import pandas as pd
df2016=pd.read_csv("https://raw.githubusercontent.com/PacktPublishing/Pandas-Cookbook/master/data/stocks_2016.csv")
df2017=pd.read_csv("https://raw.githubusercontent.com/PacktPublishing/Pandas-Cookbook/master/data/stocks_2017.csv")
df2018=pd.read_csv("https://raw.githubusercontent.com/PacktPublishing/Pandas-Cookbook/master/data/stocks_2018.csv")
df2016
df2017
df2018
pd.concat([df2016,df2017,df2018])
pd.concat([df2016,df2017,df2018]).reset_index()
pd.concat([df2016,df2017,df2018]).reset_index(drop=True)
-
R에서 rbind와 유사하다
-
rbind와의 차이점: 합치려는 데이터 프레임의 columns이 꼭 동일할 필요는 없다.
df2016
df2017.iloc[:,1:]
pd.concat([df2016,df2017.iloc[:,1:]])
-
R에서 cbind와 비슷한 느낌이다. (그런데 row의 숫자가 서로 달라도 괜찮음)
df2016
df2017
df2018
pd.concat([df2016,df2017,df2018],axis='columns')
pd.concat([df2016,df2017,df2018],axis=1)
- 칼럼이 길잖아요.. 그래서 1이에요..
df2016
df2017
df2018
pd.concat([df2016,df2017,df2018],keys=[2016,2017,2018])
-
위의 코드는 아래와 같다.
pd.concat({2016:df2016,2017:df2017,2018:df2018})
-
그런데 {2016:df2016,2017:df2017,2018:df2018}
와 dict(zip([2016,2017,2018], [df2016,df2017,df2018]))
는 같으므로 위의코드는 다시 아래와 같다.
pd.concat(dict(zip([2016,2017,2018],[df2016,df2017,df2018])))
-
의도하지 않은 코드들
pd.concat([df2016,df2017,df2018],keys=[2016,2017])
pd.concat([df2016,df2017,df2018],keys=[2016,2018])
pd.concat([df2016,df2017,df2018],keys=[2016,2017,2018,2019])
df2016
df2017
df2018
pd.concat([df2016,df2017,df2018],axis=1)
pd.concat([df2016,df2017,df2018],axis=1,keys=[2016,2017,2018])
pd.concat({2016:df2016,2017:df2017,2018:df2018},axis=1)
pd.concat(dict(zip([2016,2017,2018],[df2016,df2017,df2018])),axis=1)
import numpy as np
import pandas as pd
import folium
-
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
-
지도위에 무엇인가 오브젝트를 추가하는데, 가장 기본적인 것이 마커임 (점이라 생각해도 괜찮음)
-
마커안에 내용을 넣을 수 있음. (경우에 따라서는 유용하다)
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
-
조금 더 다양한 아이콘들을 추가하여 보자.
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
-
icon='university'
대신에 쓸만한 옵션들
- icon='street-view'
- icon='tree'
- icon='plane'
- icon='bell'
- ...
-
마커에 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
-
마커에 DataFrame (을 HTML로 바꿔서) 넣기
df= pd.DataFrame(data=[[2019,35],[2020,35],[2021,33]],columns=['Year','Enrollment'])
df.to_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>'+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
-
논리구조상 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
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
-
다양한 마커를 그냥 지옴처럼 생각해도 괜찮아보임
-
동그라미 하나 그리는데 너무 많이 노력을 하는것 같기도 함.
-
Circle이 아니라 라인, 사각형, 폴리곤등도 지도에 추가할수 있으나 더 많은 노력이 필요하다.
-
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
-
입자의 위치
단 $(x_0,y_0)=(35.837688889992634, 127.11212714586104)$ 라고 하고 $\epsilon_t$와 $\eta_t$는 서로 독립인 정규분포이다.
- 최종적인 차원: 프레임수 점의수 2
t0 = np.array([[35.837688889992634,127.11212714586104]]*3000)
walk = np.random.normal(size=(200,3000,2)) * 0.0001
t0 # 시점0
t0+walk[0,:,:]# 시점1
t0+walk[0,:,:]+walk[1,:,:]# 시점2
-
그런데 walk[0,:,:]+walk[1,:,:]
를 좀더 간단하게 쓸수 있다.
walk[0,:,:]+walk[1,:,:]
walk[:2,:,:].sum(axis=0)
-
따라서 시점2는 아래와 같이 표현가능
t0+walk[:2,:,:].sum(axis=0)
-
그렇다면 시점3은?
t0+walk[:3,:,:].sum(axis=0)
-
따라서 data 는
data = [(t0+walk[:i,:,:].sum(axis=0)).tolist() for i in range(200)]
np.array(data).shape
-
이제 data[0], data[1], data[2], ... data[199]까지 대입하여 각각 그림을 그리고 시각화하면 된다.
m=folium.Map(scrollWheelZoom=False,
location=[35.837688889992634,127.11212714586104],
zoom_start=16
)
plugins.HeatMapWithTime(data,radius=5).add_to(m)
#m