(13주차) 12월1일
pandas backend (2)
-
(1/9) pie plot / box plot (1)
-
(2/9) box plot (2)
-
(3/9) box plot (3)
-
(4/9) hist, kde, density (1)
-
(5/9) hist, kde, density (2)
-
(6/9) plotly의 융통성 (1)
-
(7/9) plotly의 융통성 (2), area plot (1)
-
(8/9) area plot (2)
-
(9/9) 잡담
import numpy as np
import pandas as pd
import warnings
from IPython.display import HTML
def show(fig):
return HTML(fig.to_html(include_plotlyjs='cdn',include_mathjax=False, config=dict({'scrollZoom':False})))
df = pd.read_csv('https://raw.githubusercontent.com/kalilurrahman/datasets/main/mobilephonemktshare2020.csv')
df
df.set_index('Date').plot.pie(y='Apple')
- 우리가 원하는 형태는 아님
-
우리가 원하는 형태로 만들기 위해서는 (1) 트랜스포즈를 해야하고 (2) 인덱스가 Samsung, Apple, ... 와 같이 회사이름이 되어야함
df.set_index('Date').T.plot.pie(y='2019-10',legend=False)
- 정상적인 플랏
df.set_index('Date').T.plot.pie(legend=False,subplots=True,layout=(4,4),figsize=(20,20))
- 사실 숫자를 비교하기 위해서는 파이차트보다 바플랏이 좋음.
- 그리고 시간에 따른 변화를 보기에는 라인차트가 좋음
-
plotly, matplotlib 백엔드 모두 지원
df = pd.read_csv('https://raw.githubusercontent.com/kalilurrahman/datasets/main/mobilephonemktshare2020.csv')
df
-
점유율의 차이를 구하자.
df.set_index('Date').diff().dropna().boxplot(figsize=(20,5))
-
위와 동일한 그림을 plotly backend로도 그릴수 있음 (plotly가 조금 융통성이 있음)
fig=df.set_index('Date').diff().dropna().boxplot(backend='plotly')
show(fig)
-
회사를 색깔별로 구분하여 범주를 만들고 싶다?
df.set_index('Date').diff().dropna().melt()
fig=df.set_index('Date').diff().dropna().melt().\
plot.box(backend='plotly',x='variable',color='variable',y='value')
show(fig)
- 색깔별로 회사를 구분하면 좋은이유? 범주를 클릭해보자
import plotly.express as px
df = px.data.tips()
df
-
팁은 대체로 얼마나 받는지?
fig=df.plot.box(backend='plotly',y='tip',height=500,width=500)
show(fig)
-
점심/저녁에 따라서 팁의 분포가 다를까?
fig=df.plot.box(backend='plotly',y='tip',x='time',height=500,width=500)
show(fig)
- 저녁에 좀더 잘주는것 같음
-
성별에 따라서도 팁을 주는것이 다를까?
fig=df.plot.box(backend='plotly',y='tip',x='time',color='sex', height=500,width=500)
show(fig)
fig=df.plot.box(backend='plotly',y='tip',x='time',color='sex', height=500,width=500, points='all')
show(fig)
- boxplot의 아웃라이어가 사라지고, 데이터를 더 리치하게 볼 수 있다.
-
요일에 따라서도 달라질까?
fig=df.plot.box(backend='plotly',y='tip',x='time',color='sex',facet_col='day', points='all')
show(fig)
-
흡연유무에 따라서도 달라질까?
fig=df.plot.box(backend='plotly',y='tip',x='time',color='sex',facet_col='day', facet_row='smoker',points='all')
show(fig)
- tidydata로 한번 만들어 두니 너무 쉽게 생각하는 대로 구현가능
-
tidydata가 확실히 고차원 자료를 그리기에 유리함. matplotlib은 위와 같은 형태를 그리는것 자체가 불가능
-
시뮬레이션예제: 정규분포를 만들어서 제곱한뒤에 3개씩, 4개씩, ... , 10개까지 더함 $\to$ 카이제곱분포
-
일단 3개부터 구현해보자.
X = np.random.normal(size=(1000,3),loc=0,scale=1)
X
X**2
-
코드를 정리하면
# ((np.random.normal(size=(1000,4),loc=0,scale=1))**2).sum(axis=1)
# ...
# ((np.random.normal(size=(1000,10),loc=0,scale=1))**2).sum(axis=1)
_arr = [3,4,5,6,7,8,9,10]
df= pd.DataFrame([((np.random.normal(size=(1000,_arr[i]),loc=0,scale=1))**2).sum(axis=1).tolist() for i in range(len(_arr))]).T
df
- 컬럼 0이 의미하는것은 정규분포를 제곱하여 3개씩 더하여 나온값이고 컬럼1이 의미하는것은 정규분포를 제곱해서 4개씩 더해서 나온값임 $\to$ 열의 이름을 지어주자.
df.columns = _arr
df
-
분포를 그려보자.
df.plot.hist()
- 알수가 없다.
-
bins와 투명도 조절
df.plot.hist(alpha=0.2,bins=50)
-
서브플랏
df.plot.hist(alpha=0.2,bins=50,layout=(2,4),subplots=True,figsize=(15,5))
plt.tight_layout()
-
kde 플랏
df.plot.kde(layout=(2,4),subplots=True,figsize=(15,5))
plt.tight_layout()
df.plot.kde(layout=(2,4),subplots=True,bw_method=0.01,figsize=(15,5))
plt.tight_layout()
df.plot.kde(layout=(2,4),subplots=True,bw_method=5,figsize=(15,5))
plt.tight_layout()
df.plot.kde(layout=(2,4),subplots=True,figsize=(15,5),ls='--')
plt.tight_layout()
-
다시 tips 예제로 돌아오자.
import plotly.express as px
df = px.data.tips()
df
-
성별에 따라서 팁을 주는게 다를까?
fig=df.plot.hist(x='tip',color='sex',backend='plotly',facet_col='sex')
show(fig)
- 빈도가 잘 보인다는 측면에서 박스플랏보다 좋은것 같음
-
시간에 따라서도 다른지?
fig=df.plot.hist(x='tip',color='sex',backend='plotly',facet_col='sex',facet_row='time')
show(fig)
- tidydata가 확실히 자료를 처리하기 편리함
-
주류플랏은 아님
-
다시 핸드폰예제
df = pd.read_csv('https://raw.githubusercontent.com/kalilurrahman/datasets/main/mobilephonemktshare2020.csv')
df
-
점유율을 area plot으로 나타내고 싶을 경우
df
df.set_index('Date').plot.area(figsize=(20,10),alpha=0.6)
- 시간에 따른 점유을의 변화를 보기에 적절한것 같다.
-
plotly를 쓰기 위해서 tidydata로 바꾸자
df.melt(id_vars='Date')
fig=df.melt(id_vars='Date').plot.area(backend='plotly',x='Date',y='value',color='variable')
show(fig)
-
위키의 테이블 크롤링.
df=pd.read_html('https://ko.wikipedia.org/wiki/%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD%EC%9D%98_%EC%9D%B8%EA%B5%AC')[19]
df
- 끔찍할 정도로 타이디 하지 않은 자료
-
첫번째 row는 일단 제외해야함
df.iloc[1:]
-
일단 스택을 해보자.
df.iloc[1:].stack()
-
서울~제주를 인덱스로 설정하고 다시 스택해보자
df.iloc[1:].columns
df.iloc[1:].set_index(('행정구역별','행정구역별')).stack()
- 나쁘지 않은 중간과정
df.iloc[1:].set_index(('행정구역별','행정구역별')).stack().reset_index()
-
시각화를 위해서 비율만 선택하도록 하자.
df.iloc[1:].set_index(('행정구역별','행정구역별')).stack().reset_index().\
query('level_1=="비율"').set_index(('행정구역별','행정구역별')).iloc[:,1:].T
-
세종시의 - 가 문제가 될듯 $\to$ 자료형도 이상함
df.iloc[1:].set_index(('행정구역별','행정구역별')).stack().reset_index().\
query('level_1=="비율"').set_index(('행정구역별','행정구역별')).iloc[:,1:].T.iloc[0,0]
-
데이터프레임의 모든 원소에 변환을 수행해야 한다. (applymap)
- 문자형을 숫자형으로 바꾸라
- 그런데 문자가 - 라면 None으로 바꿔라
(예비학습)
_x = [1,2,None,3,4]
plt.plot(_x,'o--')
(예비학습끝)
df.iloc[1:].set_index(('행정구역별','행정구역별')).stack().reset_index().\
query('level_1=="비율"').set_index(('행정구역별','행정구역별')).iloc[:,1:].T.\
applymap(lambda x: float(x) if x!='-' else None)
-
이제 그리자
import warnings
warnings.filterwarnings('ignore')
df.iloc[1:].set_index(('행정구역별','행정구역별')).stack().reset_index().\
query('level_1=="비율"').set_index(('행정구역별','행정구역별')).iloc[:,1:].T.\
applymap(lambda x: float(x) if x!='-' else None).\
plot.area(figsize=(10,10))
- 한글이 깨져서 나온다 $\to$ 고칠수 있지만 그냥 하지말자.
-
우선 타이다한 자료를 만들자.
df.iloc[1:].set_index(('행정구역별','행정구역별')).stack().applymap(lambda x: float(x) if x!='-' else None).\
stack().reset_index()
_df = _
_df
-
이름을 바꾸자.
_df.columns = pd.Index(['city','type','year','value'])
_df
-
이제 그려보자.
fig=_df.query('type=="비율"').plot.area(backend='plotly',x='year',y='value',color='city')
show(fig)