다중 공선성의 해결방안

어느정도의 X들(설명변수들)끼리의 영향은 존재할 수 밖에 없으나, 그 교집합이 심하게 겹칠 경우, 다중 공선성이 발생한다. 이 때는 적절한 변수를 선택(제거)를 하는 변수 선택법이 필요하다.

사실 X의 개수(컬럼수, 변수수)가 증가할수록 예측error가 감소하는 구간이 있다.
하지만, 적절한 복잡성을 넘어선 모델 복잡성(다중공선성으로 인해)은 과적합 = 오버피팅을 일으켜 오류가 증가하게 된다. 비록, 현재의 데이터(훈련데이터) 오류가 계속 줄어든다고 하더라도, 모르는 집단(실제데이터, 테스트 데이터)의 오류가 줄어들다가 다시 증가하는 순간이 생긴다. 이 때, 적절한 변수만 선택하여 과적합, 오버피팅을 발생시키지 않게 해야한다. 의미있는 변수들만 선택해야한다.

변수 선택법 3가지

  1. 전진 선택법(Forward selection) : X 0개부터 시작하여, 가장 유의한 변수들부터 하나씩 추가하면서, 매번 모형의 유의성을 판단한다

  2. 후진 제거법(Backward elimination) : 모든 X를 넣어놓고, 하나씩 제거해간다.

  3. 단계적 방법(stepwise selection) : 0개부터 추가했다가 뺐다가 왔다갔다함.

    • r에서 step( 모델, direction = "backward")식으로 step()함수를 이용한다. 그러면 결과창에 AIC가 찍히므로 확인한다.
  4. 의학분야 : 임상적인 의미를 가진 변수, 기존 연구에서 검증된 변수를 유의성과 관계없이 넣을 수 있다. 실제 임상에서는 단변수 -> 다변수로 체크하면서 변수를 추가하는 경우가 많다.
    예를들어, Y에 X1, X2, X3, X4, X5가 있다고 치면,
    단변수 체크 : Y ~ X1, Y ~ X2... 다 체크해서 유의성 높은 것 뽑느다. 0.05는 너무 STRICT한 기준으로 보고 0.1 ~ 0.2까지 허용해준다.
    다변수 체크 : 단변수에서 유의성이 높은 변수들을 가지고 유의성을 체크한다 Y ~ X2 + X4+ X5

### 모형 선택 기준 1. `결정계수(R^2) / 수정된 결정계수(adj R^2)` : best모델의 설명력(나머지는 설명안되는 error) / 여러모델 비교시 사용(높을수록 좋다) 2. `AIC(Akaike Information Criterion)` : -2logL + 2K (낮을수록 좋다) 3. `BIC(Baysian Information Criterion)` : -2logL + Klogn(낮을수록 좋다)

### AIC + ANOVA를 이용한 회귀모델 비교 1. `AIC(모델1, 모델1)` : 2모델 중 AIC가 낮은 모델을 선택한다. 2. `summary(모델1) (모델2)$r.squared` : 각 모델마다 설명력을 확인한다(선택에는 영향x) 3. `summary(모델1) (모델2)$adj.r.squared` : 각각의 모델에서 나온 수정된 결정계수를 비교하여 높은 모델을 선택한다. 3. `anova( 모델1, 모델2)` : `H0 : 모형1 = 모형2`가 기각되는지 `F pr(>F)`를 확인하여, `H0`가 기각되지 않고 같은 모형으로 판단된다면 **`변수가 작은 모델을 선택한다`**

### 가능한 모든 경우의수의 모델 조사 by leaps패키지 많이 쓰진 않는다고 한다. regsubsets()함수를 이용하여 nbest = size당 n개의 최적 모형을 저장하여, plot으로 그리면 된다. y축에는 adj R^2가 나오는데, 높은 모델을 사용하면 될 것이다.

회귀모형(lm())으로 만든 결과(summary())를 해석

lm( Y ~ X , data = )를 summary()로 요약하면

  1. Residual :
    Residual이라는 것이 나온다. 회귀모형으로 예측한 Y 와 실제 데이터의 Y의 차이를 의미하는 것이며, 찌꺼기로 취급해야한다.
    이 찌꺼기에는 패턴이나 추세가 있으면 안된다. 만약, plot으로 그린 결과에 어떠한 패턴이 있다면, 중요한 변수를 빠트려서 잔차에 남아있는 것이므로 찾아서 반영해줘야한다.

  2. coefficient :
    절편(b0)와 각 X의 기울기가 나온다. (Intercept)의 Estimate절편을 추정 한 값이며, 각 변수들의 Estimate기울기를 추정한 값이다.
    또한, 추정한 해당 회귀계수(절편, 기울기)에 대한 유의성을 단일표본t-test, mu = 0 (H0 : 해당 회귀계수 = 0)에 대한 p-value가 Pr(>|t|)로 표시된다.

    • 0 ~ 0.001 ***, 0.001 ~ 0.01 **, 0.01 ~ 0.05 *, 0.05 ~ 1 아무표시없음
    • 0.05이하로 H0가 기각되어야지, 해당 X의 회귀계수 0이 아니다 = 의미있는 회귀계수
    • 0.05보다 커서 H0가 기각안되면, 해당 X의 회귀계수는 0이다! -> 제외시켜야한다.
  3. multiple / Adjusted R-squared :
    먼저, ANOVA에서 나왔던 개념인 변동에 대한 이해가 필요하다. ANOVA에서는 총변동 = 그룹간변동(effect) + 그룹내변동(error)였다.
    회귀분석에서의 총 변동 = 회귀식이 설명할 수 있는 변동(effect) + 회귀식으로 설명할 수 없는 변동(error)로 구성되어있다.
    1) SST(결과변수의 총변동) = SSR + SSE
    2) SSR(Sum of Square of Regression) : 회귀식으로 설명되는 변동
    3) SSE(Sum of Square of Error) : 회귀식으로 설명하고 남은, 설명되지 않은 변동
    4) R-square(R^2) : SSR / SST (전체변동 중 회귀식으로 설명되는 변동) = 0 ~ 1

    그림으로 나타내면, 1 - SSE/SST정도인가보다.

3-1. Multiple R-squared :
결정계수 R^2(혹은 설명력 R^2)으로서, 앞에 말한 SSR/SST를 의미한다. 추정된 회귀식이 변동을 얼마나 잘 설명하는가로 해석된다.
만약, 값이 1이 나왔다면, 실제 관측값들이 회귀선상에 정확히 일치함을 의미한다.
만약, 값이 0.65 => 35%는 회귀식으로 설명할 수 없는 error임을 의미한다.
하지만, 치명적인 단점으로서 X의 개수가 증가할수록(아무상관없는 X를 추가하더라도) Multiple R-square(회귀식의 모형설명력 결정계수)도 무조건 증가하는 단점

3-2. Adjusted R-squared :
Multiple R-squared의 단점을 보완하기 위해, 보정된 R-squared(회귀식의 모형설명력, 결정계수)
변수(X)가 많아진 것을 분모에 반영하여, 변수의 개수가 고려된 R-squared(모형설명력, 결정계수)이다.

분모에 k는 변수의 개수를 의미한다.

3-3. 정리
1. Multiple R-square : BEST모델(Best회귀식)의 설명력(결정계수)
2. Adjusted R-square : 여러개의 모델을 만들어 놓은 상태에서, 좋은 모델을 찾기위해 비교시 사용되는 설명력

  1. F-statistic :

H0 : 모든 회귀계수에 대해 b1(=b2=b3=..bk)= 0을 가정한 뒤, H0를 기각시켜 회귀계수 0이 아닌 것이 적어도 하나 존재한다회귀모형의 유의성F-test한 것이다. F-검정통계량 계산은 ANOVA에서 처럼, F= SSR의평균 / SSE의평균으로 검정한다.

  • cf) 만약, 단순회귀(X1개 -> H0 : b1 = 0)일 시, coefficient의 t-test(단일표본t-test)나 모형의 F-test나 동일하다.
  • cf) F = t^2 (??) : X가 1개일때만?? 아니면 원래 분포자체가??

범주형의 X에 대한 회귀계수의 해석

앞서 숫자형 변수 X에 대해서 회귀계수(기울기)는 X가 한단위 증가시 Y의 증가량으로 해석했다.
범주형 변수 X의 경우, 범주안의 집단들 중에 1집단은 reference가 되고, 나머지 집단들이 나눠서 다른 변수처럼 표시되며, ref집단에 비해 나머지집단들의 X 한단위 증가시 Y의 증가량으로 해석된다.
예를 들어, mtcars데이터의 cyl(범주형)변수에는 4, 6, 8의 집단이 있다. 이 변수를 X(설명변수, 독립변수)로 넣어서 회귀모델을 만들면, 4집단은 표시가 안되면서 (cyl)6, (cyl)8에 대한 회귀계수가 생긴다. 해석은 (cyl)4에 비해, (cyl)6, (cyl)8집단이 Y에 어떻게 영향을 미치는지로 해석해야한다.

  • R에서 각 범주의 집단확인은 table(칼럼인덱싱)으로 하면된다. 마치 교차표 만들듯이

내부에서 작동하는 방식은 범주형을 -> 숫자형처럼 만드는 가변수Dummy 변수를 만들어서 처리한다. 집단이 3개인 경우, refence집단0,0으로 만들어놓고 나머지 2집단은 1,00,1이 될 것이다. 한 집단은 0으로 구성되어 기준이 되니, 집단수-1개의 자리수를 가지는 0과 1로 구성된다.

  • reference(기준)변수는 보통 빈도가 많거나 일반적인 집단을 기준집단으로 선택한다.

예를 들어, 약물의 종류가 P(lacebo), A(treatment A), B(treatment B)가 있다고 치자. 이때는 일반적인 집단인 P가 기준집단으로서 0으로만 구성될 것이다.

  • R에서 범주칼럼인덱싱 = relevel( factor(범주칼럼인덱싱) , ref = )로 기준집단을 직접 선택하여 더미변수화 시킬 수 있다.

표준화 회귀계수 for 회귀계수의 상대적 중요성

X-m/ sd(X)표준화시키는 목적은 단위를 고려한 비교를 위해서이다.
회귀분석전 모든 숫자형 변수들을 표준화시킨 후 회귀분석lm()을 돌리면, 표준화된 회귀계수가 얻어지며, 이것들을 plotting해서 단위를 배제시킨 회귀계수의 상대적 중요성을 확인할 수 있다. 이것은 가장 쉬운 변수 선택 방법이다.

  • SPSS로 회귀분석을 돌리면 표준화(B)+비표준화 회귀계수(b,베타)가 모두 출력된다. 그때는 표준화 회귀계수를 보고 상대적 중요성으로 해석하자!

신뢰구간은 보통 95%로 제시한다. 5%의 유의확률은 양측검정시 왼쪽 2.5%이하 <--> 오른쪽 97.5%이상의 임계치를 제시해준다. 추정한 회귀계수(기울기)가 2.5% ~ 97.5%는 확신을 가지고 있다는 것을 의미한다.
해석은 해당변수X가 1% 변화시, 종속변수Y는 추정회귀계수(2.5% ~ 97.5%)만큼 변화한다고 <<확신을 가지고 이야기할 수 있다>>

  • R에서는 confint()에 lm()결과를 넣어주면, 각 회귀계수별 신뢰구간을 제시해준다.

그러나, 이러한 해석을 위해서는 회귀분석의 가정 몇가지를 만족시켜야한다.

5-2. 회귀분석(모델링)

2019. 2. 25. 23:34

회귀분석과 로지스틱 회귀분석

  1. 회귀분석(Regression) : 관심있는 Y에 대해, X가 어떻게? 얼마나? Y에 영향을 주는지 알아보는 분석방법
  2. 로지스틱 회귀분석(Logistic Regression) : 관심있는 Y가 0 or 1일때, X가 어떻게? 얼마나? Y에 영향을 주는지 분석
    • 보통 ML과 DL의 성능에 대해서 reference로서 로지스틱 회귀분석을 먼저 제시하기도 한다.

회귀분석의 Workflow

  1. 모델링
    1) 단순 선형회귀 : Y에 영향을 주는 X가 1개
    2) 다중or중 선형회귀 : Y에 영향을 주는 X가 2개 이상

    • 다중공선성의 문제발생 : 2개 이상의 X가 서로 영향을 끼침.
  2. 모형 해석
    1) 계수 해석
    2) 표준화 계수b(베타)
    3) 계수의 유의성

  3. 모형 설명력
    1) 모형의 유의성
    2) 모델 설명력

  4. 모형 선택
    1) 변수선택기법 : 모형비교, 측도로서 AIC와 BIC

  5. 예측
    1) 잔차(residual) : 실제값 - 예측값 -> 찌꺼기인데 추세/패턴이 있는지 가정체크후 있다면 모델에 변수로 추가

1. 모델링

수학적 모형(오차없이 y=ax+b)과 다르게 통계적 모형으로서, 같은 input(x들)이라도 다른 y를 가지는 경우를 설명하기 위해 회귀방정식에는 항상 오차(엡실론)를 수반하는 형태를 가진다.

이 때, b0 = 절편, b1 = 기울기, e=오차(통계적 모형에서만 가짐)를 의미한다.
기울기 b1x가 1단위 증가할 때, y의 증가량으로 해석해야한다.
오차 e는 확률변수이며, 통계적 모형에만 적용되는 변수이다.

선형회귀는 독립변수와 종속변수의 1차 방정식을 전제로 한 선형성의 관계를 전제하여 분석한다. 그리고 데이터를 이용하여, 오차(e)를 최소화하는 방식으로 회귀방정식의 회귀계수와 회귀선을 구해야한다.
회귀선은 오차를 최소로하는 회귀방정식의 회귀계수들(b0, b1, b2 ..)을 다 구하여, 그래프상 가장 잘 설명하는 직선 하나를 찾은 것이다.

사실 회귀분석은 영국의 화학자 프랜스시 골턴이 발견한,
키 큰 부모 -> 자식들의 키는 점점 더 커지는 것이 아니라 평균으로 회귀하는 경향을 보고 만들어낸 개념이다.
독립변수 : 아버지의 키
종속변수 : 아들의 키
의 단순 선형회귀 문제로서, 키작은부모 -> 키큰자식(평균으로 가게끔), 키큰부모-> 키작은자식(평균으로가게끔)평균을 유지하려는 현상을 발견한 개념이 회귀인 것이다.

그리고 회귀분석에서 아버지의 키의 X가 1개만 있는 것이 아니라 여러개의 X들이 존재하는 것을 알 수 있다.
즉, 회귀분석이란 변수들의 관련성 규명을 위해, 어떤 수리적 모형을 가정, 측정된 데이터로 모형의 변수들을 추정하는 통계적인 방법이다.
Y에 영향을 주는 독립변수들 X에 어떤 것이 있고, 얼마나 영향을 주는지를 알아낸 뒤, 다음 Y값을 예측하는데 사용된다. 사실 예측력은 떨어지나 설명이 가능해서 자주 사용하는 분석방법이라고 한다.

예를 들어,
광고비용(X)가 매출액(Y)에 얼마나 영향을 줄까? -> 오차를 최소로하는 회귀선의 기울기로 해석한다. 광고비용 1단위 증가시 매출액 얼마나 증가했나?
공부(X)가 성적향상(Y)에 얼마나 영향을 줄까? -> 회귀선의 기울기로 해석
즉, X가 어떤 것들이 있는지 안 상태로서 선형회귀 = 회귀방정식+오차를 구한 뒤, 오차를 최소로하는 회귀선에서 기울기로 영향을 해석하면 된다.


위의 데이터에서는, X가 1개인 단순 선형회귀이며,
같은 speed(X)라도 다른 dist(Y)를 가지는데, 이는 오차(e)가 존재하기 때문이다.
dist = b0 + b1*speed + e 로 회귀식을 놓고, e를 최소화하는 b0, b1를 구해야할 것이다.

회귀식(Y = b0 + b1X + e)를 구하는 방법을 앞에서 계쏙 오차를 최소화한다고 했다.
사실, 구체적으로는 각 데이터의 실제값y와 회귀식의 값 yi의 차이인 오차(e)에 대해, 모든 오차들의 제곱의 합이 최소가 되는 회귀계수들을 구하는 방법인 최소제곱법(OLS, Ordinary Least Square)를 이용한다.
가상의 단순선형 회귀식 Y = b0 + b1X +e 에서 오차e를 좌변에 나머지를 우변에 이항한다.
e = Y - b0 - b1X
그리고, 각 데이터들을 입력하여 나오는 모든 e값들을 제곱해서 더한다.
오차의 제곱의 합을 S라 두면, 아래와 같은식이 나온다.

  1. 오차제곱의합(S, SSE)를 절편(a, b0)에 대해 편미분한다.
  2. 오차제곱의합(S, SSE)를 기울기(b, b1)에 대해서 편미분한다.
  3. 두 연립방정식을 이용하여, 절편(a)와 기울기(b)를 구할 수 있다.

이러한 방식으로 회귀계수(b0, b1-절편과 기울기)를 구하면, 회귀식이 완성된다.
이 때, 더이상 오차는 없어지고 하나의 회귀식이 만들어지는 것이다.

  • R에서는 lm()함수를 사용하면, 안에서 자동으로 b0, b1을 구해준다.
  • coefficients가 회귀계수 = Intercept(절편) + df$칼럼명(해당X앞에 곱해진 기울기)
  • lm()의 결과를 그대로 산점도 위에 abline()으로 그려주면, 그래프 상으로 회귀식을 그려줄 수 있다.
  • ggplot으로 그릴 때는, 산점도(geom_point()) + geom_smooth(method="lm")으로 자동으로 그려준다. 이 때, 신뢰구간까지 같이 그려지는데, n수가 적은 곳은 conf.interval이 넓고, n수가 많은 곳은 conf.interval이 좁다고 해석하면 된다. 좁을 수록 명사수.

사실 lm()에는 회귀계수( 절편, 해당X의 기울기들)만 있는 것이 아니라, 결과물로서 모델이 생성된다.

  • lm()결과를 reg_model변수에 저장하고, 새로운 데이터를 만들어서 predict( 모델변수명, 새로운데이터) 형식으로 predict()함수를 사용한다.


다중 공선성

이제 다중 회귀분석에 대해 다시 알아보자. Y에 영향을 미치는 X가 여러개 이므로 X to Y뿐만 아니라 X끼리 영향을 미치는 문제인 다중 공선성(Multicollinearity)의 문제가 발생한다. 즉, 독립변수(X)들간에 강한 상관관계가 나타나는 문제이다. 이것들을 어떻게 파악하고 어떻게 해결해야할까?

X들끼리의 강한 상관관계로 정보가 많아져서 Y를 예측하는데 더 좋다고 생각할 수 도 있으나, 최소제곱 추정지(OLS)의 공식상, 설명변수(X)들간의 상관관계가 높으면 OLS추정치의 분산이 불안정해진다고 한다.
다른 관점으로서 각 X들 앞에 곱해져있는 회귀계수들의 해석으로서 생각해 볼 수 있다.
X앞에 곱해져있던 b1은 가정이 있다.
다른 변수(X)들이 일정한 상황에서, 해당 X가 한단위 증가할 때 Y의 증가량이다. 즉, 다른 X들은 일정해서, 해당 X에 영향을 주지 않는 상태에서의 계수를 의미한다. 회귀계수의 정의자체가 서로 영향을 주지 않는 상태가 기본 전제인 것이다.
예를 들어, Yi = b0 + b1*X1 + b2*X2 인 상황에서, b1(기울기, X1의 회귀계수)의 해석은, X2가 일정한 상황에서 정해진 계수로서 해석하는 것이다.

만약, X1 : 태어난 날짜, X2 : 나이 처럼 X1과 X2가 완전한 상관관계(하나가 일정할 때, 를 가정이 불가능)에 있는 경우, 다중공선성 문제가 크게 발생하므로 -> 회귀계수를 정확하게 추정하기 어렵다.
또한, X1 : 상품의 내구도, X2 : 불량률 처럼 X1과 X2가 negative 상관관계가 너무 높은 경우도 다중공선성이 발생한다(하나를 일정하게 둘 수가 없다)

이러한 X들간의 상관관계를 확인하는 방법은 2가지 정도로 압축된다.

  1. X들간의 산점도그리기 : 직선성으로서 강한 상관관계를 보이면, 동시에 넣으면 안된다
  2. X들간의 VIF(Variation Inflation Factor) 혹은 공차한계(Tolerance) 계산

참고사이트 : https://datascienceschool.net/view-notebook/36176e580d124612a376cf29872cd2f0/

VIF의 역수가 Tolerance = 1 - R^2이다.

이 때, Ri^2i번째 X를 종속변수(Y)로 취급하여 회귀모형을 만든 후 Xi에 대한 나머지 X들의 모형 설명력이다.
예를 들어, Y ~ X1+ X2+ X3 모델에서, X1에 대한 VIF를 구하기 위해서 R1^2을 구해야한다. 구하는 방식은 X1 ~ X2 + X3의 모델을 만든 뒤 R1^2이 계산된다. 그 값이 0.9가 나왔다면, R1^2 0.9 = X2와 X3로 X1을 90% 설명할 수 있다.
그러면 VIF는 1 / ( 1- 0.90) 이 되고, Tolerance는 1-0.90이 된다.
이 때, VIF가 4이상 혹은 6이상 넘어가면, 해당 X는 다중공선성을 의심할 수 있다. VIF가 10(R^2 - 0.9)이상이면 보통 다중공선성 문제가 있다고 한다.

같은 이치로서, X1이 만약 다중공선성이 의심되면, 그것과 짝을 이루는 Xi가 반드시 존재할 것이다. 만약, X1과 강한 상관관계의 다중공선성을 가진 X2가 있다면, 둘중에 하나는 제거해야한다.

  • R에서는 car패키지안의 vif()함수를 이용해서 각 X에 대한 VIF를 나열해준다.

  • vif( model ) > 4라는 마스크를 만들고, True인 것을 찾아내면 된다.

  • 만약, 그러한 X가 존재한다면 최소 2개가 있을 것이다.(서로 연관)-> 1개만 선택해야한다.



다중회귀분석

Y에 영향을 끼치는 X가 여러개 있을 때는,linear combination이라는 선형결합 or 가중합으로 연결된다. 이것은 앞서, 1차 방정식으로 전제가 된다고 했다. 또한 다른 변수들이 일정할 때를 가정한 뒤, 해당 변수의 가중치(회귀계수)를 곱하는 보정이 들어간 것이다.
여기까지 만들어지는 것이 다중회귀 모형이다. 여기에는 e(엡실론)이 포함되어있다.

다음으로, 측정된 데이터들을 이용하여 OLS를 통해 오차의 제곱의 합을 최소로 하는 다중 회귀식을 구한다. e가 사라지고, 하나의 회귀식이 만들어진다.

하지만, 측정된 데이터 = 표본을 통해 만들어진 것이니, 결국에는 모집단을 추정하는 추정 다중회귀식이 만들어진다.

R에서는 lm( Y ~ X, data=)로 만들어진 단순선형회귀 모형(모델)에 대해, X를 추가해나가면서 다중선형회귀 모델이 되는 과정에서 자동으로 내부에서 회귀계수(기울기)를 보정하여 각각의 보정된 회귀계수가 summary()의 결과로 나타난다. 이 때 $coef로서, 회귀계수만 인덱싱해서 살펴보면 단순회귀와 다중회귀일때, 같은X에 대해서 다른 회귀계수가 나오는 것을 확인할 수 있다.

  • summary( lm( BMI ~ TC, data = acs) )$coef
  • summary( lm( BMI ~ TC + age + sex , data = acs) )$coef
  • TC의 Estimate=추정된 회귀계수값을 확인해보면, 변수를 추가할 때마다 회귀계수가 달라지며, 해석은 TC 한단위가 증가시 BMI의 증가량이 어떻게 변하는지 보면 된다.
  • 같이 등장하는 Pr( >|t|)는회귀계수에 대한 p-value이며,
    맨 마지막줄의 F-statistic의 p-value모형 자체의 p-value이다.
  • 즉, lm( Y ~ X의 선형모델 )은 OLS로 회귀모형을 생성
  • summary( lm())은 회귀계수 및 통계수치를 확인할 수 있다.
  • 각 회귀계수는 해당변수에 대해 다른 변수들이 일정할 때~의 가정이 있는 상태에서, 해당변수가 한 단위 증가시 종속변수가 얼마나 증가.감소하는지 로 해석하면 된다.

Tidyvers 소개

ggplot의 개발자인 Hadley Wickam의 Tidyverse패키지안에
dplyr, tidyr, tidytext, ggplot2, readr들이 다 포함되어있다.

  1. tidyverse : 포함된 패키지들 모두에서 pipe operator를 사용할 수 있다.

    • %>%를 사용하여 가독성 및 naming이 필요없어진다. 마치 ggplot의 + 연산자와 똑같음
  2. readr : read_csv()을 사용할 수 있어
    1) read.csv()보다 더 빠르다( string을 factor로 자동변환이 없음 )
    2) data.frame대신 tibble을 사용하여 최종적으로는 4~5배 빠르다고 한다.
    3) cf) data.table 패키지는 100배 이상 빠르게 사용할 수 있다고 한다.


Dplyr

가장 큰 특징 2가지는 pipe linegroup별 계산인데, 세부적으로 아래와 같다.

  1. select() : 쉽게 필요한 칼럼만 인덱싱 or 새로운칼럼명 = 으로 칼럼명 변경

    • select( data, 칼럼명)
    • select( data, c()없이 여러개 칼럼명 연결, 1, 2, 3)
    • select( data, starts_wwith("칼럼명 시작단어 선택")
    • select( data, ends_wwith("칼럼명 끝단어 선택")
    • select( data, contains("포함 단어 선택")
    • select( data, 새로운칼럼명 = 뽑아낸 칼럼 )
  2. filter() : 쉽게 필요한 행(특정범주)만 인덱싱

    • filter( data, 칼럼명 조건 )
    • filter( data, 칼럼명 조건 & 칼럼명2 조건2 )
  3. arrange() : 쉽게 오름/내림차순 정렬

    • arrange( data, 오름차순 정렬기준칼럼명 )
    • arrange( data, desc(오름차순 정렬기준칼럼명) )
  4. mutate() : 쉽게 새로운 칼럼 생성 by 기존칼럼를 변형

    • mutate( data, 새로운칼럼명 = 기존칼럼명 + 수식 )
  5. group_by() & Summarise() : 그룹별 통계량

    • filter()로 필요행(특정범주)인덱싱 후 summarise( filtedData, mean(칼럼명, na.rm=T)
    • filter() -> group_by( filterdData, 기준칼럼명 ) -> summarise( groupedData, 통계함수 ) 그룹별 통계
  6. %>% : 파이프라인

    • data %>% filter( 칼럼명과 조건) %>% group_by( 기준칼럼명 ) %>% summarise( 집계함수))
    • 각 함수에서 data부분만 생략됨
  7. 그외 count, sample


Tidyr으로 데이터 reshape

  1. spread() : to wide
  2. gather() : to long

R markdown

Untitled

Dplyr

  • dplyr has 5 verbs which make up the majority of the data manipulation tasks we perform.
  • 1.Select: used to select one or more columns;
  • 2.Filter: used to select some rows based on specific criteria;
  • 3.Arrange: used to sort data based on one or more columns in ascending or descending order;
  • 4.Mutate: used to add new columns to our data;
  • 5.Summarise: used to create chunks(묶음) from our data.

파이프라인 및 전체 연습

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(moonBook)

#### 파이프라인 없이 해보기
# 1. filter()로 행인덱싱(특정범주 가져오기)
acs2 <- filter( acs, sex == "Female" & age > 40)
# 2. arrange()로 내림차순 정렬
ordered_acs2 <- arrange( acs2, desc(height))
# 3. group_by()로 그룹화 -> tibble로 변형 & 그룹화를 직접적으로 하진 않음
obesity_to_acs2 <- group_by(ordered_acs2, obesity)
head(obesity_to_acs2) # tibble상에서는 그룹화 안되어있음. 그룹별 집계가 가능한 상태만 Groups로 표시
## # A tibble: 6 x 17
## # Groups:   obesity [2]
##     age sex   cardiogenicShock entry Dx       EF height weight   BMI
##   <int> <chr> <chr>            <chr> <chr> <dbl>  <dbl>  <dbl> <dbl>
## 1    67 Fema~ No               Radi~ Unst~  57.2    168     52  18.4
## 2    89 Fema~ No               Femo~ STEMI  21.8    165     50  18.4
## 3    64 Fema~ No               Radi~ Unst~  57.7    165     74  27.2
## 4    53 Fema~ No               Radi~ Unst~  58.4    165     75  27.5
## 5    64 Fema~ No               Radi~ STEMI  59      165     71  26.1
## 6    48 Fema~ No               Radi~ STEMI  61.5    165     58  21.3
## # ... with 8 more variables: obesity <chr>, TC <dbl>, LDLC <int>,
## #   HDLC <int>, TG <int>, DM <chr>, HBP <chr>, smoking <chr>
# 4. summarise()로 그룹별 집계
obesity_to_BMI_mean <- summarise(obesity_to_acs2, mean( BMI, na.rm = T))


#### 파이프라인을 통해 naming걱정없이 바로 해보기
acs %>%
  filter( sex == "Female" & age > 40) %>%
  arrange( desc(height))  %>%
  group_by( obesity ) %>%
  summarise( mean( BMI, na.rm = T))
## # A tibble: 2 x 2
##   obesity `mean(BMI, na.rm = T)`
##   <chr>                    <dbl>
## 1 No                        22.2
## 2 Yes                       27.7

select() : 필료한 칼럼인덱싱 & 칼럼명 변경도 가느

library(dplyr)
head(iris) # 내장 데이터
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
# select() - 필요한 칼럼만 인덱싱
head( select( iris, Sepal.Length) )
##   Sepal.Length
## 1          5.1
## 2          4.9
## 3          4.7
## 4          4.6
## 5          5.0
## 6          5.4
head( select( iris, Sepal.Length, Sepal.Width) )
##   Sepal.Length Sepal.Width
## 1          5.1         3.5
## 2          4.9         3.0
## 3          4.7         3.2
## 4          4.6         3.1
## 5          5.0         3.6
## 6          5.4         3.9
# select() - 특정조건의 칼럼명 뽑아내기
head( select( iris, starts_with( "Sepal")) ) # Sepal 로 시작하는 칼럼명만인덱싱
##   Sepal.Length Sepal.Width
## 1          5.1         3.5
## 2          4.9         3.0
## 3          4.7         3.2
## 4          4.6         3.1
## 5          5.0         3.6
## 6          5.4         3.9
head( select( iris, ends_with( "Width")) )
##   Sepal.Width Petal.Width
## 1         3.5         0.2
## 2         3.0         0.2
## 3         3.2         0.2
## 4         3.1         0.2
## 5         3.6         0.2
## 6         3.9         0.4
head( select( iris, contains( "etal")) ) # contain아님 contains
##   Petal.Length Petal.Width
## 1          1.4         0.2
## 2          1.4         0.2
## 3          1.3         0.2
## 4          1.5         0.2
## 5          1.4         0.2
## 6          1.7         0.4
# select() - 칼럼명 변경해서 인덱싱
head( select( iris, petal = Petal.Length) )
##   petal
## 1   1.4
## 2   1.4
## 3   1.3
## 4   1.5
## 5   1.4
## 6   1.7
head( select( iris, petal = starts_with("Petal")) ) # 인덱싱 칼럼 2개를 하나의 칼럼명에 넣으면 뒤에 숫자 1, 2 붙어서 칼럼명 생성 ex> petal1, petal2
##   petal1 petal2
## 1    1.4    0.2
## 2    1.4    0.2
## 3    1.3    0.2
## 4    1.5    0.2
## 5    1.4    0.2
## 6    1.7    0.4

filter() - 행인덱싱, 특정범주 인덱싱

head(airquality)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5
## 6    28      NA 14.9   66     5   6
head( filter( airquality, Temp > 70) )
##   Ozone Solar.R Wind Temp Month Day
## 1    36     118  8.0   72     5   2
## 2    12     149 12.6   74     5   3
## 3     7      NA  6.9   74     5  11
## 4    11     320 16.6   73     5  22
## 5    45     252 14.9   81     5  29
## 6   115     223  5.7   79     5  30
head( filter( airquality, Temp > 70 & Month > 5) )
##   Ozone Solar.R Wind Temp Month Day
## 1    NA     286  8.6   78     6   1
## 2    NA     287  9.7   74     6   2
## 3    NA     186  9.2   84     6   4
## 4    NA     220  8.6   85     6   5
## 5    NA     264 14.3   79     6   6
## 6    29     127  9.7   82     6   7

arrange()

# default는 오름차순
head( arrange( airquality, Ozone) )
##   Ozone Solar.R Wind Temp Month Day
## 1     1       8  9.7   59     5  21
## 2     4      25  9.7   61     5  23
## 3     6      78 18.4   57     5  18
## 4     7      NA  6.9   74     5  11
## 5     7      48 14.3   80     7  15
## 6     7      49 10.3   69     9  24
# desc(기준칼럼명) 내림차순
head( arrange( airquality, desc(Ozone)) )
##   Ozone Solar.R Wind Temp Month Day
## 1   168     238  3.4   81     8  25
## 2   135     269  4.1   84     7   1
## 3   122     255  4.0   89     8   7
## 4   118     225  2.3   94     8  29
## 5   115     223  5.7   79     5  30
## 6   110     207  8.0   90     8   9
# 기준을 2개로
head( arrange( airquality, desc(Ozone), Day) )
##   Ozone Solar.R Wind Temp Month Day
## 1   168     238  3.4   81     8  25
## 2   135     269  4.1   84     7   1
## 3   122     255  4.0   89     8   7
## 4   118     225  2.3   94     8  29
## 5   115     223  5.7   79     5  30
## 6   110     207  8.0   90     8   9

mutate() - 기존칼럼 + 수식으로 새로운 칼럼 생성(한 df return)

head( mutate( airquality, TempInc = (Temp - 32) * 5 / 9) )
##   Ozone Solar.R Wind Temp Month Day  TempInc
## 1    41     190  7.4   67     5   1 19.44444
## 2    36     118  8.0   72     5   2 22.22222
## 3    12     149 12.6   74     5   3 23.33333
## 4    18     313 11.5   62     5   4 16.66667
## 5    NA      NA 14.3   56     5   5 13.33333
## 6    28      NA 14.9   66     5   6 18.88889

summarise() with group_by()

# group_by()안하더라도, 집계한다.
summarise(airquality, mean(Temp, na.rm = T))
##   mean(Temp, na.rm = T)
## 1              77.88235
# group_by()와 함께
summarise(group_by(airquality, Month), mean(Temp, na.rm = T))
## # A tibble: 5 x 2
##   Month `mean(Temp, na.rm = T)`
##   <int>                   <dbl>
## 1     5                    65.5
## 2     6                    79.1
## 3     7                    83.9
## 4     8                    84.0
## 5     9                    76.9

연습해보기

  • COPD데이터에서 성별 남자만 추출 -> 흡연이력으로 group_by()후 BMI의 평균을 summarise
library(moonBook)
data(acs)
head(acs)
##   age    sex cardiogenicShock   entry              Dx   EF height weight
## 1  62   Male               No Femoral           STEMI 18.0    168     72
## 2  78 Female               No Femoral           STEMI 18.4    148     48
## 3  76 Female              Yes Femoral           STEMI 20.0     NA     NA
## 4  89 Female               No Femoral           STEMI 21.8    165     50
## 5  56   Male               No  Radial          NSTEMI 21.8    162     64
## 6  73 Female               No  Radial Unstable Angina 22.0    153     59
##        BMI obesity  TC LDLC HDLC  TG  DM HBP smoking
## 1 25.51020     Yes 215  154   35 155 Yes  No  Smoker
## 2 21.91381      No  NA   NA   NA 166  No Yes   Never
## 3       NA      No  NA   NA   NA  NA  No Yes   Never
## 4 18.36547      No 121   73   20  89  No  No   Never
## 5 24.38653      No 195  151   36  63 Yes Yes  Smoker
## 6 25.20398     Yes 184  112   38 137 Yes Yes   Never
acs %>%
  filter( sex == "Male") %>%
  group_by( smoking ) %>%
  summarise( mean(BMI, na.rm = T))
## # A tibble: 3 x 2
##   smoking   `mean(BMI, na.rm = T)`
##   <chr>                      <dbl>
## 1 Ex-smoker                   24.5
## 2 Never                       24.4
## 3 Smoker                      24.2

다운로드 : https://public.tableau.com/en-us/s/download
예시데이터 : https://github.com/is2js/jupyter_python/blob/master/Global%20Superstore.xls

단축키 : F7 - 전체화면(프리젠테이션 모드)
기본개념 : 범주칼럼은 열 / 숫자형칼럼은 행 / 위도,경도,지역명 등은 더블클릭으로 자동배정

범주별 숫자를 tableu로 정렬 / 색상(범례) / 필터링

  1. tablue public 버전을 설치한다.


  2. 예시데이터(엑셀)을 아래와 같이 열거나 or 파일을 tableu에 드래그 한 뒤,
    기존 엑셀파일 속 sheet가 왼쪽 메뉴에 나열되어있다.
    하나를 선택해 준다.



  1. 왼쪽메뉴에서 시트를 선택해주면, 아래 [시트1]이 생긴다.

    • 차원 : 범주형에 속하는 칼럼들
    • 측정값 : 숫자형에 속하는 칼럼들이 자동 배정된다.
  2. 차원에 있는 범주 중 category칼럼을 -> 열에 ,
    측정값에 있는 숫자형 sale칼럼을 -> 행으로 드래그해보자.
    열로 주면, 그래프의 x축의 범주로 / 행으로 주면 y축의 값으로 간다.

  3. 열(범주), 행(숫자)가 나열된 상태에서 우측상단의 [표현방식]을 바꾸면 그래프의 모양을 선택할 수 있다.

  4. 메뉴아이콘 중에 [마크 레이블 표시]를 누르면, 그래프상의 수치를 다 표현해준다.

  1. 메뉴아이콘 중 [오름/내림차순]을 선택하면, 원본 순서이외에 크기순으로 정렬해준다.

  2. 범주로서 열에 배정한 category칼럼을, 다시 왼쪽에서 가져와 [색상]에 드래그 해주면 색을 나타낸다.
    우측상단에 카테고리칼럼이 색상을 나타내고 있다는 범례도 표시된다.


  3. 범주로서 열에 배정한 category칼럼을, 다시 왼쪽에서 가져와 [필터]에 드래그 한뒤, category칼럼의 화살표를 내려 [필터표시]를 한 뒤, 우측에서 [클릭을 통해 필터링]해보자.









위도,경도,지역명을 가진 데이터에서 숫자형을 크기+색상gradient로 표시

  1. 위도/경도 데이터는 더블클릭만으로 자동 배정된다.

  1. country 칼럼도 더블클릭만으로 자동으로 마크의 [원]에 배정되는 것 같다.

  1. 현재까지는 위도+경도+county명으로 지도에 표시가 된 상태다.
    여기에 county별(원) 숫자형인 sale를 <원의 크기>로 나타내고 싶어서 [크기]에 드래그했다.
    sale(여러 행에 같은 것이 있을 수 있으니) 합계로 표시가 된다.
    county별(원별) sale(원의 크기)별로 마크의 크기가 결정되었다.

  2. Discount를 [색상]으로 추가하면, county(원)별 sale(원의크기)별 discount(원의 색상)으로 나타날 것이다.
    색상의 기본은 discount의 합계별로 파란색gradient로 나타난다.

큰 discount에는 빨간색 <-> 낮은 discount에는 파란색이 나타나도록 [색상] - [색상편집] - [빨간색 - 파란색 다중] - [반전](빨간색이 높은수치로 이동)을 선택해주자.






범주별 숫자데이터를, 연도별(페이지별)로 보기 + 시계열로 그리기

  1. [시트3]을 생성한 뒤, category -> 열 / sale -> 행에 배정하자

  2. ship date(년월일, 날짜)칼럼을 -> [페이지]에 배정하면 [플레이]버튼이 생긴다.
    날짜칼럼은 기본으로 [년]을 기준으로 그려진다.


  3. 플레이 버튼을 누르면, 년도별로 1년씩 증가하면서 해당 데이터가 변한다
    직접 년도를 선택할 수 있다.


  4. [표현방식]을 lineplot으로 바꾸면, 페이지로 년도별로 볼 순 없지만, 시게열 데이터가 된다.



대쉬보드 = 지금껏 만든 시트들 통합

  1. 하단이 메뉴에서 시트가 아닌 [새 대쉬보드]를 만든다.

  1. 기본적으로 크기가 작게 배정되어있으므로 [크기] - [범위] - [자동]을 선택해 최대화 시켜준다.

  2. 지금까지 만들어둔 시트1, 2, 3을 원하는 위치에 드래그해놓고 크기를 조절한다.





  1. 시트1에서 만든 category의 범주 [필터]는 시트1에만 작동한다.
    대쉬보드안의 모든 시트(1,2,3)에 작동할 수 있도록, [필터 우클릭] - [워크시트에 적용]
    • [이 데이터원본을 사용하는 모든 항목]을 적용해주면, 대쉬보드 안의 모든 시트에 다 적용된다.
    • 년도를 조절하는 [페이지]도 시트2에만 적용되어있다. 이것은 모든 페이지에 옵션이 안보이는 것 같다.



  1. [F7]로 프리젠테이션모드(전체화면)에서 사용해본다.


+ Recent posts