중선형 회귀(Multiple Linear Regression)는 하나 이상의 독립 변수가 사용된 선형 회귀다. 즉, Y = β_0 +(β_1)(X_1) + (β_2)(X_2) + … + (β_p)(X_p) + ε처럼 여러 독립 변수가 사용된 형태의 모델을 말한다. 중선형 회귀 모델을 만들고 평가하는 방법에 대해 살펴보자.
모델 생성 및 평가
중선형 회귀에서 lm()에 지정하는 포뮬러는 독립 변수가 여러 개므로, 단순 선형 회귀에 비해 복잡한 형태다. 여러 독립 변수가 주어지면 이들을 +로 연결해 나열하여 중선형 회귀 모델을 만들 수 있다. 다음 코드는 아이리스 데이터의 Sepal.Length를 Sepal.Width, Petal.Length, Petal.Width를 사용해 예측하는 모델을 만든다.
>(m<-lm(Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width, data=iris)) Call: lm(formula = Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width, data = iris) Coefficients: (Intercept) Sepal.Width Petal.Length Petal.Width 1.8560 0.6508 0.7091 -0.5565 |
모델의 세부 내용은 단순 선형 회귀와 마찬가지로 summary()로 볼 수 있다.
>summary(m) Call: lm(formula = Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width, data = iris) Residuals: Min 1Q Median 3Q Max -0.82816 -0.21989 0.01875 0.19709 0.84570 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 1.85600 0.25078 7.401 9.85e-12 *** Sepal.Width 0.65084 0.06665 9.765 < 2e-16 *** Petal.Length 0.70913 0.05672 12.502 < 2e-16 *** Petal.Width -0.55648 0.12755 -4.363 2.41e-05 *** --- Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 Residual standard error: 0.3145 on 146 degrees of freedom Multiple R-squared: 0.8586, Adjusted R-squared: 0.8557 F-statistic: 295.5 on 3 and 146 DF, p-value: < 2.2e-16 |
모델의 계수를 읽는 방법이나 summary()의 결과를 읽는 방법은 앞서 살펴본 단순 선형 회귀와 동일하다. 위 결과에서는 Sepal.Width, Petal.Lnegth, Petal.Width의 p 값이 모두 0.05보다 작아 모두 중요한 설명 변수다.
F 통계량(F-statistic)은 단순 선형 회귀와 가설에 차이가 있는데, 단순 선형 회귀의 귀무가설은 β_0 + β_1 × X + ε에서 ‘H_0: β_1 = 0’인 반면, 중선형 회귀에서의 귀무가설은 ‘H_0: 모든 계수가 0이다(즉, β_0 = β_1 = … = β_p = 0)’이다. 따라서 p-value < 0.05면 하나 이상의 설명 변수의 계수가 0이 아니다.
범주형 변수
앞에서는 범주형 변수인 Species를 설명 변수에서 생략했다. Species를 포함하려면 ‘+ Species’를 포뮬러에 추가해 설명 변수를 더해주거나, 단순히 ‘Sepal.Length ~ . ’로 포뮬러를 적는다. 여기서 ‘.’은 종속 변수를 제외한 모든 변수를 의미한다. 다음은 ‘Sepal.Length ~ . ’를 사용한 선형 회귀의 예다.
>(m<-lm(Sepal.Length ~ ., data=iris)) Call: lm(formula = Sepal.Length ~ ., data = iris) Coefficients: (Intercept) Sepal.Width Petal.Length 2.1713 0.4959 0.8292 Petal.Width Speciesversicolor Speciesvirginica -0.3152 -0.7236 -1.0235 >summary(m) Call: lm(formula = Sepal.Length ~ ., data = iris) Residuals: Min 1Q Median 3Q Max -0.79424 -0.21874 0.00899 0.20255 0.73103 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 2.17127 0.27979 7.760 1.43e-12 *** Sepal.Width 0.49589 0.08607 5.761 4.87e-08 *** Petal.Length 0.82924 0.06853 12.101 < 2e-16 *** Petal.Width -0.31516 0.15120 -2.084 0.03889 * Speciesversicolor -0.72356 0.24017 -3.013 0.00306 ** Speciesvirginica -1.02350 0.33373 -3.067 0.00258 ** --- Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 Residual standard error: 0.3068 on 144 degrees of freedom Multiple R-squared: 0.8673, Adjusted R-squared: 0.8627 F-statistic: 188.3 on 5 and 144 DF, p-value: < 2.2e-16 |
Species를 추가한 모델에서는 Speciesversicolor와 Speciesvirginica라는 두 계수가 더 보인다. Species는 이외에도 setosa가 있는데, 위 결과에는 Speciessetosa 계수가 없다. 그 이유는 범주형 변수 Species를 다음과 같이 2개의 가변수(dummy variable)를 사용해 표현했기 때문이다.
표현하고자 하는 Species | Speciesversicolor | Speciesvirginica |
setosa | 0 | 0 |
versicolor | 1 | 0 |
virginica | 0 | 1 |
데이터가 어떻게 코딩되는지를 살펴보고 싶다면 model.matrix() 함수를 사용한다.
-model.matrix : 디자인(또는 모델) 행렬을 생성한다.
model.matrix(
# 객체, 포뮬러 또는 terms 객체. lm을 인자로 주면 model.matrix.lm( )이 호출되고,
# 이 함수가 적절한 인자를 model.matrix()에 넘겨준다.
object,
data=environment(object) # 데이터 프레임
)
다음은 iris 데이터의 1행, 51행, 101행 데이터가 어떻게 코딩되어 모델에 사용되는지를 보여준다. 아이리스에서 1행은 setosa, 51행은 versicolor, 101행은 virginica 종에 대한 데이터임을 상기하기 바란다.
>model.matrix(m)[c(1, 51, 101), ] (Intercept) Sepal.Width Petal.Length Petal.Width Speciesversicolor Speciesvirginica 1 1 3.5 1.4 0.2 0 0 51 1 3.2 4.7 1.4 1 0 101 1 3.3 6.0 2.5 0 |
이렇게 만들어진 모델은 Species별로 Sepal.Length에 대해 다음과 같은 세 가지 모델을 만든 셈이다(편의를 위해 소수점 3자리 이하를 버리고 오차항은 생략함).
Species | 모델 |
setosa | 2.17 + Sepal.Width * 0.49 + Petal.Length * 0.82 + Petal.Width * (-0.31) |
versicolor | 2.17 - 0.72 + Sepal.Width * 0.49 + Petal.Length * 0.82 + Petal.Width * (-0.31) |
virginica | 2.17 - 1.02 + Sepal.Width * 0.49 + Petal.Length * 0.82 + Petal.Width * (-0.31) |
이 모델은 Species별로 절편만 다르고 그 외 부분은 동일하다. 만약 Species별로 다른 설명 변수의 계수까지 다르게 설정하고 싶다면 Species와 다른 열의 상호 작용을 모델링해야 한다. 설명 변수 간 상호 작용은 "상호 작용" 절에서 다루기로 하자. 상호 작용을 고려한 다양한 모델 설명에 대해서는 참고자료 에서 "Analysis of Covariance" 절을 참고하기 바란다.
anova()를 사용해 분산 분석 결과를 보자.
>anova(m) Analysis of Variance Table Response: Sepal.Length Df Sum Sq Mean Sq F value Pr(>F) Sepal.Width 1 1.412 1.412 15.0011 0.0001625 *** Petal.Length 1 84.427 84.427 896.8059 < 2.2e-16 *** Petal.Width 1 1.883 1.883 20.0055 1.556e-05 *** Species 2 0.889 0.444 4.7212 0.0103288 * Residuals 144 13.556 0.094 --- Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 |
summary()로 살펴볼 때와는 달리 anova( )의 결과에서는 Species가 하나의 설명 변수로 묶여서 표시된다. 이 표를 보면 Species의 p 값은 0.0103288이므로 유의미한 설명 변수(즉, 가설 검정 시 Species의 계수를 0으로 볼 수 없다)임을 알 수 있다.
중선형 회귀 모델의 시각화
앞서 ‘Sepal.Length ~ . ’로부터 만든 모델은 여러 개의 독립 변수를 사용했다. 그러나 2차원 이상의 데이터는 쉽게 표시할 수 없으므로 여기서는 Species와 Sepal.Width만 사용해 시각화를 해보자. 다음은 아이리스 데이터를 Species별로 Sepal.Width, Sepal.Length 차원에 산점도로 그린 예다.
>with(iris, plot(Sepal.Width, Sepal.Length, + cex=.7, + pch=as.numeric(Species))) |
위 코드에서 cex는 점의 크기를 지정하는 옵션이며, pch는 점의 형태를 정한다. as.numeric()을 Species인 범주형 변수에 적용했으므로 Species의 종별로 1, 2, 3의 값을 갖게 된다. 즉, pch는 다음과 같이 지정된다.
>as.numeric(iris$Species) [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 [38] 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 [75] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 3 [112] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 [149] 3 3 |
다음은 회귀 직선을 그릴 차례다. Sepal.Width와 Species만 사용하기로 했으므로 모델을 새로 적합하고 계수를 구한다.
>m<-lm(Sepal.Length ~ Sepal.Width + Species, data=iris) >coef(m) (Intercept) Sepal.Width Speciesversicolor Speciesvirginica 2.2513932 0.8035609 1.4587431 1.9468166 |
회귀 직선은 abline()을 사용해 그린다. abline()의 첫 번째 인자는 절편, 두 번째 인자는 기울기며 lty는 선의 유형을 지정한다.
>abline(2.25, 0.80, lty=1) >abline(2.25 + 1.45, 0.80, lty=2) >abline(2.25 + 1.94, 0.80, lty=3) |
알아보기 쉽게 legend()를 사용해 범례를 표시하자.
>legend("topright", levels(iris$Species), pch=1:3, bg="white") |
위 코드에서 bg=“white”는 배경을 흰색으로 칠해준다. 이렇게 하면 범주가 표시된 사각형 안의 데이터는 가려지므로 범주를 읽기 편해진다. pch는 앞서 plot()에서 사용한 1, 2, 3을 차례로 지정한 것이다. levels()는 범주형 변수의 각 레벨의 이름을 반환한다. levels(iris$Species)의 결과는 다음과 같다.
>levels(iris$Species) [1] "setosa" "versicolor" "virginica" |
코드를 한 번에 정리하면 다음과 같다.
>with(iris, plot(Sepal.Width, Sepal.Length, + cex=.7, + pch=as.numeric(Species))) >m< lm(Sepal.Length ~ Sepal.Width + Species, data=iris) >coef(m) (Intercept) Sepal.Width Speciesversicolor Speciesvirginica 2.2513932 0.8035609 1.4587431 1.9468166 >abline(2.25, 0.80, lty=1) >abline(2.25 + 1.45, 0.80, lty=2) >abline(2.25 + 1.94, 0.80, lty=3) >legend("topright", levels(iris$Species), pch=1:3, bg="white") |
결과는 그림 8-6에 보였다.
표현식을 위한 I()의 사용
지금까지 본 중선형 회귀의 포뮬러는 독립 변수와 종속 변수의 관계를 1차식으로 표현 가능했다. 그러나 경우에 따라서는 종속 변수가 독립 변수의 2차 이상에 비례하는 Y = X^2 + 3X + 5 + ε과 같은 경우가 있을 수 있다. 또는 Y = 3×(X_1 + X_2) + ε처럼 두 변수의 합을 하나의 변수로 보고 회귀 분석을 하고자 할 때도 있다.
이러한 경우에는 I() 안에 원하는 수식을 표현한다.
- I : 객체의 해석(interpretation)과 변환(conversion)을 방지한다. data.frame() 또는 포뮬러에 객체를 지정할 때 변환을 방지한다.
I(
x # 객체
)
다음은 Y = X^2 + 3X + 5 + ε의 회귀 계수를 찾는 예다.
>x<-1:1000 >y<-x^2 + 3 * x + 5 + rnorm(1000) >lm(y ~ I(x^2) + x) Call: lm(formula = y ~ I(x^2) + x) Coefficients: (Intercept) I(x^2) x 5.109 1.000 2.999 |
위 코드에서는 1 ~ 1000 값을 가진 x로부터 종속 변수 y를 만들었다. 그 뒤 formula에 y ~ I(x^2) + x를 지정해 계수를 찾았다.
I(x^2) 대신 x^2를 사용하면 에러는 발생하지 않지만 전혀 다른 결과를 얻게 된다.
>lm(y ~ x^2) Call: lm(formula = y ~ x^2) Coefficients: (Intercept) x -167162 1004 |
그 이유는 lm에 formula 인자로 주어진 x^2는 x × x기 때문이다. x × x는 x + x + x:x와 같은 의미로, ‘x 변수, x 변수, x와 x의 상호 작용’을 의미한다. 이에 대해서는 "summaryBy()" 절의 ‘포뮬러 해석하기’에서 포뮬러의 일반적인 모양을 설명하며 알아본 바 있다. 상호 작용에 대해서는 "상호 작용" 절에서 다시 다룬다.
다음은 Y = 3(X_1 + X_2) + ε의 예다.
>x1 <- 1:1000 >x2 <- 3 * x1 >y <- 3 * (x1 + x2) + rnorm(1000) >lm(y ~ I(x1 + x2)) Call: lm(formula = y ~ I(x1 + x2)) Coefficients: (Intercept) I(x1 + x2) -0.02753 3.00002 |
보다시피 X_1 + X_2의 계수와 절편이 각각 3, 0에 가까운 값으로 구해졌다.
같은 데이터에 대해 y ~ x_1 + x_2를 포뮬러로 지정하면 다음과 같이 X_1과 X_2를 별개로 취급한 모델을 구하게 된다.
>lm(y ~ x1 + x2) Call: lm(formula = y ~ x_1 + x_2) Coefficients: (Intercept) x_1 x_2 -0.02753 12.00007 NA |
변수의 변환
종속 변수에 log를 취하거나 설명 변수에 제곱근을 취하는 등의 변환은 formula에 곧바로 수식을 적어 할 수 있다.
다음은 Y = e^(X+ε)의 관계가 있는 X, Y가 있을 때, log(Y)를 종속 변수로 하고 X를 설명 변수로 하여 회귀 직선을 구한 예다.
>x<-101:200 >y<-exp(3 * x + rnorm(100)) >lm(log(y) ~ x) Call: lm(formula = log(y) ~ x) Coefficients: (Intercept) x -0.05137 2.99944 |
반대로 설명 변수에 log()를 취하는 예를 보자. 다음은 Y = log(X) + ε에 대해 회귀 직선을 구하는 예다.
>x<-101:200 >y<-log(x) + rnorm(100) >lm(y ~ log(x)) Call: lm(formula = y ~ log(x)) Coefficients: (Intercept) log(x) 3.7496 0.2615 |
이외에도 exp(), sqrt() 등의 함수를 formula에 사용할 수 있다.
상호 작용
상호 작용(Interaction)은 독립 변수 간의 상호 작용이 종속 변수에 영향을 주는 경우를 말한다. 또, 이 영향을 주는 방법이 합이 아니라 곱의 형태일 때를 말한다.
지금까지 계속 살펴본 자동차의 주행 속도와 제동 거리의 예를 생각해보자. 이 데이터는 (주행 속도, 제동 거리)의 순서쌍 데이터로 구성되어 있고, 단순 선형 회귀 모델은 dist = β_0 + β_1 × speed + ε 형태였다. 그러나 이 데이터에 자동차의 크기(소형, 대형의 두 가지 범주형 변수)가 추가된다면 자동차의 크기를 설명 변수에 추가해야 할 것이다.
자동차의 크기는 상호 작용을 어떻게 고려하는가에 따라 모델을 그림 8-7에 보인 세 가지 경우로 나누어 생각할 수 있다.
그림 8-7의 세 가지 유형은 다음과 같이 설명할 수 있다.
- (a) 차량의 크기를 고려할 필요가 없다고 가정한 모델로, 제동 거리는 주행 속도에만 비례한다.
- (b) 차량의 크기는 상수항에만 영향을 미칠 뿐 주행 속도에 따른 제동 거리의 기울기에는 영향을 미치지 않는 경우다.
- (c) 차량의 크기가 상수항과 주행 속도의 기울기 모두에 영향을 미치는 경우다.
이들 각각을 lm()의 포뮬러로 표현하면 다음과 같다.
- (a) dist ~ speed
- (b) dist ~ speed + size
- (c) dist ~ speed + size + speed:size 또는 dist ~ speed * size
(b)의 경우는 speed와 size가 모두 dist에 영향을 주지만 speed로 인한 영향과 size로 인한 영향이 합쳐져 dist가 되었다. 즉, dist = β_0 + (β_1)*speed + β_2 * size + ε 형태다. 이 경우는 종속 변수에 영향을 주는 방법이 ‘합’의 형태므로 상호 작용이라고 부르지 않는다.
(c)의 경우가 이 절에서 설명할 상호 작용에 해당한다. 상호 작용은 두 변수 speed와 dist를 ‘:’으로 연결해 speed:dist로 표현한다. 그리고 개별 변수와 상호 작용을 모두 포뮬러에 표현하는 speed + dist + speed:dist는 speed * dist로 축약하여 표현할 수 있다.
3개 이상의 변수 A, B, C와 그 상호 작용은 어떻게 표현할까? 모든 상호 작용을 표현한다면 A + B + C + A:B + A:C + B:C + A:B:C를 지정하면 된다. 그리고 이는 A * B * C로 축약할 수 있다.
그러나 A, B, C 3개 변수가 있는데 세 변수가 동시에 상호 작용할 수는 없고 최대 2개까지 상호 작용한다면 A + B + C + A:B + A:C + B:C라고 적는다. 그리고 이를 축약해 표현하는 방법이 바로 (A + B + C)^2다. 마찬가지로 설명 변수 A, B, C, D가 있고 이들 중 최대 2개 변수가 상호 작용하며 개별 변수 역시 포뮬러에 표현한다면 (A + B + C + D)^2가 된다. 또, 최대 3개 변수가 상호 작용한다면 (A + B + C + D)^3으로 표현할 수 있다.
이런 까닭에 설명 변수 X의 제곱을 포뮬러에 사용하고 싶다면 I(X^2)처럼 I( )를 사용해야 한다. 그렇지 않으면 X^2가 설명 변수 X와 X:X로 해석되어버리기 때문이다. 마찬가지로 (X + Y)^2는 X + Y + X:Y를 뜻하지만 I((X+Y)^2)는 X와 Y의 합의 제곱을 뜻한다.
좀 더 다양한 포뮬러의 예는 참고자료를 참고하기 바란다.
지금까지 살펴본 내용을 Orange 데이터 셋에 적용해보자. Orange 데이터는 오렌지 나무Tree별 수령age과 둘레(circumference)를 저장한 데이터다.
>data(Orange) >Orange Tree age circumference 1 1 118 30 2 1 484 58 3 1 664 87 4 1 1004 115 5 1 1231 120 6 1 1372 142 7 1 1582 145 8 2 118 33 9 2 484 69 10 2 664 111 11 2 1004 156 12 2 1231 172 ... |
Orange 데이터에서 age는 Tree별로 모두 동일한 나이인 118, 484, 664, …, 1582일 때 측정되었다. 따라서 모델을 만들기에 앞서 Tree와 circumference 간 상호 연관 관계를 다음처럼 plot( )으로 시각화해볼 수 있다.
>with(Orange, + plot(Tree, circumference, xlab="tree", ylab="circumference")) |
좀 더 일반적으로 데이터의 상호 작용을 살펴보는 그림은 상호 작용 그래프(interaction plot)며, interaction.plot()을 사용해 그릴 수 있다.
-interaction.plot : 상호 작용 그래프를 그린다.
interaction.plot(
x.factor, # X 축에 그릴 팩터
trace.factor, # 자취를 그릴 레벨을 저장한 팩터
response # 반응값을 저장한 숫자 벡터
)
다음은 Orange 데이터에서 age, Tree의 상호 작용이 circumference에 어떤 영향을 주는지 알아보기 위해 상호 작용 그래프를 그린 예다.
>with(Orange, interaction.plot(age, Tree, circumference)) |
그림 8-9에서 볼 수 있듯이 나무의 수령이 높아짐에 따라 둘레가 길어지는 추세가 관찰되었다. 그리고 어떤 나무인가에 따라 수령과 둘레의 관계는 서로 다른 것으로 보인다.
lm()을 사용해 선형 회귀를 수행해보자. 그러기 위해서는 Tree열을 수정할 필요가 있다. 이 절에서 다루고자 하는 내용은 범주형 변수와 연속형 변수의 상호 작용이다. 반면 Orange$Tree는 순서가 있는 범주형 변수(Ordered Factor)므로, 이를 순서가 없는 명목형 변수로 바꿔준다.
>Orange[,"fTree"] <- factor(Orange[, "Tree"], ordered=FALSE) |
다음은 fTree, age, fTree:age를 설명 변수로 선형 회귀를 수행하는 코드다.
>m<-lm(circumference ~ fTree * age, data=Orange) >anova(m) Analysis of Variance Table Response: circumference Df Sum Sq Mean Sq F value Pr(>F) fTree 4 11841 2960 27.2983 8.428e-09 *** age 1 93772 93772 864.7348 < 2.2e-16 *** fTree:age 4 4043 1011 9.3206 9.402e-05 *** Residuals 25 2711 108 --- Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 |
보다시피 fTree, age 두 설명 변수가 모두 p 값이 0.05보다 작아 유의한 것으로 나타났다. 둘의 상호 작용인 fTree:age 역시 유의한 것으로 보인다
이 절의 시작 부분에서 상호 작용은 ‘곱’의 형태라고 설명했다. 또, "범주형 변수" 절에서 선형 회귀를 수행할 때 범주형 변수는 가변수로 바뀐다고 설명했다. 상호 작용이 있을 때 model.matrix를 살펴보면 이 두 가지 사실을 모두 확인할 수 있다.
>head(model.matrix(m)) (Intercept) fTree1 fTree5 fTree2 fTree4 age fTree1:age fTree5:age fTree2:age fTree4:age 1 1 1 0 0 0 118 118 0 0 0 2 1 1 0 0 0 484 484 0 0 0 3 1 1 0 0 0 664 664 0 0 0 4 1 1 0 0 0 1004 1004 0 0 0 5 1 1 0 0 0 1231 1231 0 0 0 6 1 1 0 0 0 1372 1372 0 0 0 |
위 결과를 보면, fTree는 fTree1, fTree5, fTree2, fTree4라는 4개의 가변수로 표현되었음을 알 수 있다. 또, age와 fTree의 상호 작용은 fTree1:age, fTree5:age, fTree2:age, fTree4:age로 표현되었다.
좀 더 보기 쉽게 age와 연관이 있는 열들만 뽑아보자.
>mm<-model.matrix(m) >mm[, grep("age", colnames(mm))] age fTree1:age fTree5:age fTree2:age fTree4:age 1 118 118 0 0 0 2 484 484 0 0 0 3 664 664 0 0 0 4 1004 1004 0 0 0 5 1231 1231 0 0 0 6 1372 1372 0 0 0 7 1582 1582 0 0 0 8 118 0 0 118 0 9 484 0 0 484 0 10 664 0 0 664 0 11 1004 0 0 1004 0 12 1231 0 0 1231 0 13 1372 0 0 1372 0 14 1582 0 0 1582 0 15 118 0 0 0 0 16 484 0 0 0 0 17 664 0 0 0 0 18 1004 0 0 0 0 19 1231 0 0 0 0 20 1372 0 0 0 0 21 1582 0 0 0 0 22 118 0 0 0 118 23 484 0 0 0 484 24 664 0 0 0 664 25 1004 0 0 0 1004 26 1231 0 0 0 1231 27 1372 0 0 0 1372 28 1582 0 0 0 1582 29 118 0 118 0 0 30 484 0 484 0 0 31 664 0 664 0 0 32 1004 0 1004 0 0 33 1231 0 1231 0 0 34 1372 0 1372 0 0 35 1582 0 1582 0 0 |
grep()은 패턴과 문자열을 인자로 받아 패턴이 문자열 내에 존재하면 1, 그렇지 않으면 0으로 반환하는 함수다. 따라서 grep(“age”, colnames(mm))은 age라는 문자열이 열 이름에 존재하면 1, 그렇지 않으면 0을 반환하므로 age가 포함된 열의 선택을 쉽게 해준다.
결과를 보면 age열은 각 데이터의 age를 그대로 담고 있지만, 상호 작용을 뜻하는 fTree1:age는 1 ~ 7행에 대해서만 age를 갖고 있고 8 ~ 35행에 대해서는 age 값을 갖고 있지 않다. fTree5:age, fTree2:age, fTree4:age도 마찬가지로 일부 행에만 age 값이 들어 있다. 그 이유는 이들 상호 작용을 뜻하는 열들은 포뮬러에 주어진 fTree * age 그대로 가변수 fTreeN에 들어 있는 1 또는 0의 값과 age를 곱한 값을 담고 있기 때문이다.
따라서 가변수가 1인 열에서는 age 값이 상호 작용 열에 나타나지만, 가변수가 0인 열에 대해서는 상호 작용 열의 값이 0으로 나타난다. 이러한 방식으로 행렬을 만듦으로써 ‘곱’의 형태인 상호 작용을 고려한 선형 회귀를 수행하는 것이다.
순서형 범주형 변수 Tree를 사용한 선형 회귀와 더 다양한 시각화를 수행한 내용은 참고자료를 보기 바란다.
R을 이용한 데이터 처리&분석 실무 中