자료실

조절효과 심화)존슨 네이만 방법 및 그래프

이재희
2023-08-28
조회수 210

조절효과는 분석방법 중에서 쉬운 편에 속한다. 

하지만 좀 더 들여다보면 어려운 테크닉이 필요한데 바로 상호작용 탐색에 대한 것이다. 

단순기울기 방법은 매우 쉽지만 좀 더 정교하게 임계치를 구해내는 것은 쉽지 않은데, 

R 프로그램을 통해서는 쉽게 해낼 수 있다. 


 조절변인의 어느 영역에서 조절효과가 유의하고 다른 영역에서는 유의하지 않은지를 조사하는 과정을 ‘상호작용 탐색(probing an interaction)‘이라고 한다.  이러한 분석이 필요한 이유는 위계적 중다회귀분석은 조절효과가 유의하게 나타난다는 결과만 보여주고  조절변인의  전체 영역 중에서 어느 구간에서 조절효과가 유의한지에 대한 결과는 제시되지 않기 때문이다. 


상호작용 탐색은 존슨-네이만 방법(Johnson-Neyman technique) 혹은 특정값 선택방법(pick-a-point approach) 을 사용하게 된다. 존슨-네이만 방법(Johnson-Neyman technique)은  조명등 분석법(floodlight analysis; Spiller et al., 2013)이라고도 알려져 있다. 이 방법은 단순기울기 분석(simple slopes)으로 알려진 특정값 선택방법(pick-a-point approach) 보다 더 우수한 것으로 알려져 있다. 단순기울기 분석을 적용하면 조절변인의 일부 특정값을 선택하게 되는데(ex. M, M±1SD), 이러한 선택은 자의적 선택이라는 제한점을 가짐과 동시에 표본에 의한 영향을 받을 가능성이 높다. 반면, 존슨-네이만 방법을 적용하면 조건부효과와 표준오차의 비율이 정확히 tcritical (p = α 에 해당하는 t의 임계치)값을 가지는 조절변인의 값을 확인할 수 있다. 



아래 그래프는 존슨=네이만 방법을 통해 나온 그래프이다. 

설명을 하자면,  그래프에서 임계치가  48.63으로 되어있는데 이는 신뢰구간의 상한과 하한이 둘 다 0을 포함하지 않다가, 포함하게 되는 지점이다.  즉 48.63점을 넘어가면 더 이상 유의하지 않게 되는 것이다. 


그림 아래에는 R에서 그래프를 그리는 코드이니 필요하신 분들은 참고해서 사용하시면 되겠다. 



result1 <- lm(so_to ~ str_to *tra_5 , dfrm ) # 독립 조절 -> 종속


jnt = function(.lm, predictor, moderator, alpha=.05) {

require(stringi)

b1 = coef(.lm)[predictor]

b3 = coef(.lm)[stri_startswith_fixed(names(coef(.lm)), paste0(predictor,":")) | stri_endswith_fixed(names(coef(.lm)), paste0(":",predictor))]

se_b1 = coef(summary(.lm))[predictor, 2]

se_b3 = coef(summary(.lm))[stri_startswith_fixed(names(coef(.lm)), paste0(predictor,":")) | stri_endswith_fixed(names(coef(.lm)), paste0(":",predictor)), 2]

COV_b1b3 = vcov(.lm)[predictor, stri_startswith_fixed(names(coef(.lm)), paste0(predictor,":")) | stri_endswith_fixed(names(coef(.lm)), paste0(":",predictor))]

t_crit = qt(1-alpha/2, .lm$df.residual)

# see Bauer & Curran, 2005

a = t_crit^2 * se_b3^2 - b3^2

b = 2 * (t_crit^2 * COV_b1b3 - b1 * b3)

c = t_crit^2 * se_b1^2 - b1^2

jn = c(

(-b - sqrt(b^2 - 4 * a * c)) / (2 * a),

(-b + sqrt(b^2 - 4 * a * c)) / (2 * a)

)

JN = sort(unname(jn))

JN = JN[JN>=min(.lm$model[,moderator]) & JN<=max(.lm$model[,moderator])]

JN

}


#설정------------------

jnt(result1, predictor = "str_to", moderator = "tra_5", alpha = .05)




theta_plot = function(.lm, predictor, moderator, alpha=.05, jn=F) {

require(dplyr)

require(ggplot2); theme_set(theme_minimal())

require(stringi)

.data = data_frame(b1 = coef(.lm)[predictor],

b3 = coef(.lm)[stri_startswith_fixed(names(coef(.lm)), paste0(predictor,":")) | stri_endswith_fixed(names(coef(.lm)), paste0(":",predictor))],

Z = quantile(.lm$model[,moderator], seq(0,1,.01)),

theta = b1 + Z * b3,

se_b1 = coef(summary(.lm))[predictor, 2],

COV_b1b3 = vcov(.lm)[predictor, stri_startswith_fixed(names(coef(.lm)), paste0(predictor,":")) | stri_endswith_fixed(names(coef(.lm)), paste0(":",predictor))],

se_b3 = coef(summary(.lm))[stri_startswith_fixed(names(coef(.lm)), paste0(predictor,":")) | stri_endswith_fixed(names(coef(.lm)), paste0(":",predictor)), 2],

se_theta = sqrt(se_b1^2 + 2 * Z * COV_b1b3 + Z^2 * se_b3^2),

ci.lo_theta = theta+qt(alpha/2, .lm$df.residual)*se_theta,

ci.hi_theta = theta+qt(1-alpha/2, .lm$df.residual)*se_theta)

if (jn) {

JN = jnt(.lm=.lm, predictor=predictor, moderator=moderator, alpha=alpha)

JN_lines = geom_vline(xintercept=JN, linetype=2)

JN_regions = ifelse(length(JN) == 0, "no significance regions", paste(round(JN,2), collapse = "; "))

Xlab = paste0("개념화 기술", " (JN Significance Regions: ", JN_regions,")")

} # paste0("자기통합") 부분은 수정해줘야 함!! 

else {

Xlab = moderator


JN_lines = NULL

}

.data %>%

ggplot(aes(Z, theta, ymin=ci.lo_theta, ymax=ci.hi_theta)) + geom_ribbon(alpha = .2) + geom_line() + 

geom_hline(yintercept=0, linetype=2) + labs(x = Xlab, y= "조절효과 ") + JN_lines

}





theta_plot(result1, predictor = "str_to", moderator = "tra_5" , alpha = .05, jn = T)


tmp_plot = theta_plot(result1, predictor = "str_to ", moderator = "tra_5", alpha = .05, jn = T)

class(tmp_plot)

tmp_plot