Bland-Altman 플롯은 두 가지 측정 방법 간의 일치 정도(agreement)를 평가하는 데 사용하는 그래프입니다.
예를 하나 들어봅시다. 혈압을 측정하는 혈압계 A와 B가 있고 5명의 혈압을 아래와 같이 측정했다고 합시다.
피험자 | A 혈압계 | B혈압계 |
1 | 120 | 122 |
2 | 130 | 128 |
3 | 125 | 127 |
4 | 140 | 146 |
5 | 150 | 159 |
두 혈압계의 결과가 잘 일치하는지 그래프로 나타내고 싶다고 합시다. 여러가지 방법이 있겠지만 두 방법의 일치 정도를 시각적으로 보기 위해서는 Blank-Altman plot이 좋습니다. 왜 좋은지는 Blank-Altman plot을 그려보면 알 수 있습니다.
Blank-Altman 플롯 그리는 방법
먼저 아래와 같이 두 값의 평균과 차이를 계산해줍니다.
피험자 | A 혈압계 | B 혈압계 | 평균 | 차이 (A-B) |
1 | 120 | 122 | 121 | -2 |
2 | 130 | 128 | 129 | 2 |
3 | 125 | 127 | 126 | -2 |
4 | 140 | 146 | 143 | -6 |
5 | 150 | 159 | 154.5 | -9 |
Blank-Altman 플롯은 X축을 평균으로, Y축을 차이로 그린 그래프입니다. 그려보면 아래와 같습니다.

R코드 글 맨 뒤에 첨부하겠습니다. Blant-Altman 플롯을 그리면 단순히 산점도를 그리는 것보다 많은 정보를 확인할 수 있습니다.
1. 차이평균을 확인할 수 있습니다. 이 값이 0에 가까울 수록 일치도가 높습니다.
2. 차이평균을 기준으로 95% SD 구간을 확인할 수 있습니다. 이 구간의 범위가 너무 크면 일치도가 낮은 것입니다. 이 범위가 임상적으로 허용 가능한지 판단해야 합니다.
3. 혈압계의 값에 따른 차이의 크기를 확인할 수 있습니다. 위 그래프의 경우 혈압이 높을 때 차이가 크게 발생한 것을 확인할 수 있습니다.
4. Outlier 를 쉽게 확인할 수 있습니다.
맺는말
두 가지 측정 방법 간의 일치도를 시각화하는 방법에는 여러 가지가 있습니다. 예전에는 단순히 두 결과를 산점도로 그려보거나, 차이 값을 막대그래프로 표시하는 방식이 주로 사용되었을 것입니다. 하지만 이러한 방법들은 한계가 있었고, 이런 시행착오 끝에 Bland-Altman 플롯이 고안되었습니다. 알고 보면 복잡한 내용은 아니지만, 직관적이고 해석이 쉽기 때문에 현재까지도 널리 사용되는 유용한 도구입니다.
첨부자료
#R코드
# 데이터 입력
A <- c(120, 130, 125, 140, 150)
B <- c(122, 128, 127, 146, 159)
# 평균과 차이 계산
mean_values <- (A + B) / 2
diff_values <- A - B
# 평균 차이와 표준편차, limits of agreement
mean_diff <- mean(diff_values)
std_diff <- sd(diff_values)
loa_upper <- mean_diff + 1.96 * std_diff
loa_lower <- mean_diff - 1.96 * std_diff
# 블랜드-알트만 플롯 그리기
plot(mean_values, diff_values,
main = "Bland-Altman Plot",
xlab = "두 혈압계의 평균값",
ylab = "차이 (A - B)",
pch = 19, # 점 모양
ylim = c(min(diff_values, loa_lower) - 2, max(diff_values, loa_upper) + 2)
)
abline(h = mean_diff, col = "red", lty = 2) # 평균 차이 선
abline(h = loa_upper, col = "blue", lty = 3) # 상한선
abline(h = loa_lower, col = "blue", lty = 3) # 하한선
# 격자 추가
grid()
# 선 옆에 주석 추가
text(x = max(mean_values)-5, y = mean_diff, labels = paste0("mean_diff: ", round(mean_diff, 2)), pos = 3, col = "red")
text(x = max(mean_values)-5, y = loa_upper, labels = paste0("mean_diff+1.96SD: ", round(loa_upper, 2)), pos = 3, col = "blue")
text(x = max(mean_values)-5, y = loa_lower, labels = paste0("mean_diff-1.96SD: ", round(loa_lower, 2)), pos = 1, col = "blue")
'@ 통계 교양 > 통계 Tips' 카테고리의 다른 글
두사람이 데이터를 두번씩 측정했다면 ICC는 어떻게 비교해야 할까? (1) | 2024.10.23 |
---|---|
오즈비 95% 신뢰구간 직접 구하는 방법 (0) | 2023.12.15 |
마르코브 연쇄 쉽게 이해하기 (0) | 2023.11.09 |
자기회귀모델 (Autoregressive model) 쉽게 이해하기 (0) | 2023.11.06 |
다중공선성 확인하는 방법 (분산팽창요인 VIF) (0) | 2023.10.30 |
표준화 회귀계수가 뭔가요? (0) | 2023.10.25 |
다중회귀분석에서 왜 수정된 결정계수를 사용하는가? (0) | 2023.10.24 |
표본 크기가 커지면 정규성을 따르지 않는 문제 (0) | 2023.09.19 |
댓글
bigpicture님의
글이 좋았다면 응원을 보내주세요!
이 글이 도움이 됐다면, 응원 댓글을 써보세요. 블로거에게 지급되는 응원금은 새로운 창작의 큰 힘이 됩니다.
응원 댓글은 만 14세 이상 카카오계정 이용자라면 누구나 편하게 작성, 결제할 수 있습니다.
글 본문, 댓글 목록 등을 통해 응원한 팬과 응원 댓글, 응원금을 강조해 보여줍니다.
응원금은 앱에서는 인앱결제, 웹에서는 카카오페이 및 신용카드로 결제할 수 있습니다.