(6주차) 10월18일
Partial correlation
-
(1/4) 아이스크림을 많이 먹으면 걸리는 병
-
(2/4) 기상청기온자료를 활용하여 가짜자료 구축 및 해석 (1)
-
(3/4) 기상청기온자료를 활용하여 가짜자료 구축 및 해석 (2)
-
(4/4) plotnine을 활용한 시각화
-
내용요약
- 여름 $\to$ 수영장 $\to$ 소아마비
- 여름 $\to$ 아이스크림
- 아이스크림과 소아마비는 상관관계가 높다: 아이스크림 성분중에서 소아마비를 유발하는 유해물질이 있을 것이다 (?)
-
아래와 같이 모형을 간단하게 하자.
- 온도 $\to$ 소아마비
- 온도 $\to$ 아이스크림
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
-
교재의 예제상황은 예를들면 아래와 같다.
-
아이스크림 판매량 = 20 + 온도 $\times$ 2 + $\epsilon$
np.random.seed(1)
temp= np.array([-10.2, -5.2, 0.1, 10.1, 12.2, 14.7,
25.4, 26.8, 28.9, 35.1, 32.2, 34.6])
ϵ1= np.random.normal(size=12,scale=5)
icecream= 20 + temp * 2 + ϵ1
plt.plot(temp,icecream,'.')
- 온도와 아이스크림 판매량의 산점도
-
소아마비 = 30 + 온도 $\times$ 0.5 + $\epsilon^*$
np.random.seed(2)
ϵ2= np.random.normal(size=12,scale=5)
disease = 30+ temp* 0.5 + ϵ2
plt.plot(temp,disease,'.')
- 온도와 소아마비의 산점도
-
아이스크림과 질병의 산점도를 그려보자.
plt.plot(icecream,disease,'.')
- 양의 상관관계에 있다.
-
아이스크림 중 어떠한 물질이 소아마비를 일으키는것이 분명하므로 (인과성이 분명해보이니까) 아래와 같은 모형을 세우자. <-- 여기서부터 틀렸음
$${\tt disease}_i =\beta_0 +\beta_1 {\tt icecream}_i +\epsilon_i,\quad \textbf{for} ~~ i=1,2,\dots, 12$$
-
적절한 $\beta_0$와 $\beta_1$을 추정하면 우리는 아이스크림과 소아마비의 관계를 알 수 있다. <-- 틀린주장
- 틀린 모형
- 도데체 우리가 뭘 잘못했는가?
-
두 변수 사이에 상관관계가 있어도 실제 원인은 다른 변수에 숨겨져 있는 경우가 많다.
- 예제의상황: 아이스크림과 익사자도 양의 상관관계에 있을것이다.
- 아이스크림을 먹이면 물에 빠져 죽는다 $\to$ 틀린주장
- 사실 기온이 숨겨진 원인이다. 기온이 증가하면 아이스크림 판매량도 증가하고 폭염때문에 익사사고율도 높아지는 구조이다.
-
아래와 같은 예제를 생각하자.
- 인구수 $\to$ 교회
- 인구수 $\to$ 범죄건수
- 지역별 교회와 범죄건수를 살펴보면 상관관계가 높게 나올것임
-
교회를 많이 지으면 범죄건수도 증가한다?
- 사실 그렇지 않다.
- 인구수가 비슷한 도시끼리 묶어서 비교해보면 교회와 범죄건수는 양의 상관관계에 있지 않을것임
-
올바른 분석: 온도가 비슷한 그룹끼리 묶어서 그려보자. $\to$ 상관계수가 줄어들 것이다.
plt.plot(icecream[:6],disease[:6],'.')
plt.plot(icecream[6:],disease[6:],'.')
-
진짜로 선형관계가 약해졌다..
-
위의 toy example은 데이터가 너무 작아서 억지스러움
df=pd.read_csv('https://raw.githubusercontent.com/guebin/2021DV/master/_notebooks/extremum.csv')
df
-
평균기온만 선택하여 뽑자.
pd.Series(df.columns)
temp=np.array(df.iloc[:,3])
len(temp)
-
아이스크림 판매량
np.random.seed(1)
ϵ1=np.random.normal(size=656, scale=10)
icecream=temp*2 + 30 + ϵ1
plt.plot(temp,icecream,'.')
-
소아마비
np.random.seed(2)
ϵ2=np.random.normal(size=656,scale=1)
disease=temp*0.5 + 40 +ϵ2
plt.plot(temp,disease,'.')
-
아이스크림과 소아마비
plt.plot(icecream,disease,'.')
np.corrcoef(icecream,disease)
- 0.86정도..
-
여름만 뽑아서 그러보면?
plt.plot(icecream[temp>25],disease[temp>25], '.') ## 평균기온이 25도가 넘어가면 여름
-
산점도
fig , ((ax1,ax2), (ax3,ax4)) = plt.subplots(2,2)
ax1.plot(temp,icecream,'.')
ax2.plot(temp,disease,'.')
ax3.plot(icecream,disease,'.')
ax4.plot(icecream[temp>25],disease[temp>25],'.')
fig , ((ax1,ax2), (ax3,ax4)) = plt.subplots(2,2)
ax1.plot(temp,icecream,'.')
ax2.plot(temp,disease,'.')
ax3.plot(icecream,disease,'.')
ax4.plot(icecream,disease,'.')
ax4.plot(icecream[temp>25],disease[temp>25],'.')
-
목표: 모든 온도구간에 대하여 각각 색을 다르게 하여 그려보자.
- 사실 지금 변수는 온도, 아이스크림판매량, 소아마비
- 지금까지는 기본산점도만 사용하였기에 2차원플랏만 그렸음 $\to$ 그래서 각각의 산점도를 정신없이 그려왔음
- 온도가 유사한 지역을 색으로 묶으면 3차원 플랏이 가능함
-
일단 데이터 프레임을 정리하자.
df1=pd.DataFrame({'temp':temp, 'icecream':icecream, 'disease':disease})
df1
-
온도를 카테고리화 하자 $\to$ 적당한 구긴을 설정하기 위해서 히스토그램을 그려보자.
df1.temp.hist()
plt.hist(df1.temp)
-
구간은 5정도로 하면 적당할것 같다.
def f(x):
if x<0:
y='group0'
elif x<5:
y='group5'
elif x<10:
y='group10'
elif x<15:
y='group15'
elif x<20:
y='group20'
elif x<25:
y='group25'
else:
y='group30'
return y
df1['temp2']=list(map(f,df1.temp))
df1
from plotnine import *
ggplot(data=df1)+geom_point(aes(x='icecream',y='disease',colour='temp2'),alpha=0.5)
ggplot(data=df1)+geom_point(aes(x='icecream',y='disease',colour='temp2'),alpha=0.2)+geom_smooth(aes(x='icecream',y='disease',colour='temp2'),size=2,linetype='dashed')
-
온도를 통제하니까 아이스크림과 질병은 관련이 없어보인다.
np.random.seed(1)
ϵ1=np.random.normal(size=656, scale=10)
icecream=temp*2 + 30 + ϵ1
np.random.seed(2)
ϵ2=np.random.normal(size=656,scale=1)
disease= 30+ temp*0.0 + icecream*0.15 +ϵ2*2
df2=pd.DataFrame({'temp':temp,'icecream':icecream,'disease':disease})
df2['temp2']=list(map(f,df2.temp))
df2
ggplot(data=df2)+geom_point(aes(x='icecream',y='disease',colour='temp2'),alpha=0.2)+geom_smooth(aes(x='icecream',y='disease',colour='temp2'),size=2,linetype='dashed')
df1.corr()
df2.corr()
-
온도구간을 10으로 변경하고 df1, df2에서 아이스크림과 소아마비의 산점도를 시각화한뒤 스크린샷 제출