[Funnel plot으로 순위지정 없이 다수 그룹 비교하기]
1. Introduction
지난 시간, 우리는 Funnel plot이 어디에 사용되고, 어떤 방법론을 따르는지에 대해 배웠습니다. 이번 시간에는 Funnel plot을 이용하여 이상치를 탐지하고, 순위를 결정하는 실습을 진행하겠습니다. 본 실습의 의미는, 실제 데이터처럼 Unbalance 한 값을 가지고 Funnel Plot을 생성해 보겠습니다.
2. Data
title "Temperatures of Car Roofs";
title2 "71 Degrees (F) in the Shade";
data CarTemps;
infile datalines missover;
input color $8. Temperature @;
do while (^missing(Temperature));
output;
input Temperature @;
end;
datalines;
black 145.5 154.0 143.0 126.5 128.0 131.5 128.5 141.5
blue 134.5 123.0 113.5 126.0 139.0 125.5 143.5
burgundy 131.0 141.0 141.5 122.0
gray 124.0 141.5 128.0 127.5 132.0 130.0
green 149.5 130.5 114.0 129.5
red 140.5 128.5 124.5 119.5 132.0 126.0
silver 118.5 112.5 96.5 105.5 111.0 103.5
tan 127.0 103.5 121.0 113.0
white 103.5 97.5 93.0 99.0 91.5 104.5 99.5
;
run;
위 코드를 이용하여 데이터를 불러와 줍니다. 데이터는 Clark Anderson의 실험에서 추출된 “주차된 자동차 지붕의 온도” 입니다. do while (^missing(Temperature)); 문은 데이터가 결측치일 때까지 불러온다는 뜻입니다.
3. practice
proc iml;
use CarTemps;
read all var {Color Temperature};
close CarTemps;
위 코드를 사용하여 CarTemps에 대한 IML을 실행시킵니다.
u = unique(Color); /** 색 반환**/
p = ncol(u);/** 컬럼 개수 **/
mean = j(p,1); sem = j(p,1); n = j(p,1);
do i = 1 to p;
idx = loc(Color=u[i]);
n[i] = ncol(idx);
T = Temperature[idx];
mean[i] = T[:];
sem[i] = sqrt(var(T)/n[i]); /** var는 분산을 계산하는 함수입니다. **/
end;
p는 컬럼 개수를 의미하고, u는 색을 반환합니다.
Unique와 LOC 함수를 이용하여 샘플 크기와 평균을 구합니다. Sem[i]는 표준 오차를 의미합니다. (Loc에 대한 설명은 앞선 포스팅을 참고하시기 바랍니다.)
평균을 구하는데 이렇게 복잡한 과정이 필요한 이유는, 실제 데이터는 이처럼 카테고리 별로 다른 값들을 가지고 있기때문입니다. 평균 계산 시 범주별로 샘플 수 계산이 필요합니다.
call sortndx(jdx, mean, 1, 1);
color = u[jdx]; n = n[jdx];
mean = mean[jdx]; sem = sem[jdx];
print color n mean[format=5.1] sem[format=4.1];
/** 데이터 셋 저장 **/
create Temp var {color n mean sem};
append;
close Temp;
위 코드는 계산된 평균을 이용하여 내림차순으로 정리하는 과정입니다. 배열의 인덱스를 통해 각 값들을 불러와 mean과sem에 입력하여 줍니다. 지금까지 만든 값들로 Create 문을 사용하여 temp라는 행렬을 제작합니다.
코드를 실행하면 위와 같은 결과가 출력됩니다. 각 색의 그룹별로 개수, 평균, 오차를 확인할 수 있습니다. 본 실습에서는 각 색의 관측치별로 유의한 차이가 있는지 확인하기 때문에, 색을 그룹으로 나누어 계산하는 것이 타당합니다.
y = Temperature[:];
s = sqrt(var(Temperature));
print y s[label="StdDev"];
이제 실질적인 데이터 비교를 위해, 전체 데이터의 평균과 표준편차를 계산합니다.
Y를 전체 평균, s를 표준편차로 두었습니다.
코드를 실행하면 위와 같은 결과가 생성됩니다.
n = T( do(3, 8.5, 0.1) ); /*Funnel 분포를 위한 n값 설정*/
p = {0.001 0.025 0.975 0.999}; /** 유의수준 범위 설정 **/
z = quantile("normal", p);
/** 56 x 4의 신뢰수준 데이터가 생성됩니다. (n 3부터 8.5까지 0.1간격, 56개) **/
limits = y + s/sqrt(n)*z;
print limits;
이제 Funnel plot의 기능을 맛보기 위해, 정규성을 검정할 데이터와 확인하고 싶은 분위 수를 지정합니다. Limits는N의 개수가 증가함에 따라 점점 좁아지는 유의성 검정 범위를 반영합니다. (깔때기 모양을 형성함. 개체수가 많아질수록 편향이 작아지기 때문)
d = n || limits;
varNames = {"N" "L998" "L95" "U95" "U998"};
create Bounds from d[c=varNames];
append from d;
close Bounds;
quit;
d는 ||를 이용하여 n과 limits를 합쳐준 행렬입니다. [N의 개수에 따라 limits의 범위가 달라지는 것은 Funnel Plot의 특징입니다. 이전 포스팅에서 말씀드렸다시피, Funnel Plot은 “관측치가 많을수록 작은 편향을 가지고 관측치가 적을수록 큰 편향를 가지는” 데이터의 특징을 응용한 기법입니다.]
d를 이용해 제작된 Bounds 데이터를 확인해 보면,
이처럼 N이 커질수록 하위 유의성 검정 범위는 증가하고, 상위의 유의성 검정 범위는 감소하는 것을 확인할 수 있습니다. 이를 통해 Funnel Plot의 정규성 데이터 범위가 깔때기 모양을 띄는 것을 확인할 수 있습니다.(밑의 그래프를 보시면 이해에 도움이 됩니다.)
data All;
set Temp Bounds;
run;
proc sgplot data=All;
scatter x=N y=Mean /datalabel=Color;
refline 123.4 / axis=y;
band x=N lower=L95 upper=U95 / nofill
name="CI95" LegendLabel="95% limits"
lineattrs=(color=gray);
band x=N lower=L998 upper=U998 / nofill
name="CI998" LegendLabel="99.8% limits"
lineattrs=(pattern=dash color=gray);
xaxis label="Number of Cars";
yaxis label="Average Temperature";
keylegend "CI998" "CI95" /
location=inside position=TopRight
across=1;
run;
위 코드를 사용하여, 온도와 정규성 범위 데이터를 합친 그래프를 작성합니다.
N이 증가함에 따라 데이터 편차가 감소함을 관측하기 위해 N값을 X축으로 두었습니다.
그래프 설정을 99.8퍼센트에서 점선으로 표현하고, 95퍼센트는 실선으로 표현하였습니다. 이를 통해 어떤 데이터가 어느 유의수준에 포함되는지 확인할 수 있습니다.
N이 증가함에 따라 온도의 정규성 검정이 깔때기 모양을 띄는 것을 알 수 있습니다.
“무채색은 열 흡수에 따른 온도 변화가 유채색과 차이가 있는가”인 가설 하에 그래프를 해석해보면, Black과 silver는 0.5의 유의수준 하에 이상치(혹은 차이가 있는 값)로 분류되는 것을 알 수 있습니다. 만약 더 높은 수준인 0.002를 유의수준으로 설정한다면, White만이 유의한 차이가 있는 값으로 볼 수 있습니다.
4. Conclusion
이렇게 전체와 그룹의 평균을 이용하여 가설을 검정하거나, 이상치를 탐지할 수도 있고, 데이터 분포를 확인할 수도 있습니다. Funnel Plot은 N의 차이에 따른 편향을 반영한 것이어서 그룹 간의 개체 수 차이가 심할 때 유용하게 사용할수 있습니다.
다만 이번 실습의 한계로 다중비교에 대한 통제를 기입하지 않은 점이 있습니다. 또한, n에 대해 임의로 0.1 간격의관측 값들을 생성한 것입니다. (원활한 신뢰한계 수준을 보기 위해) n의 값이 수백, 수천개가 되는 데이터에선 이런문제가 해결될 것이라고 생각합니다.
참고
-https://blogs.sas.com/content/iml/2011/04/15/funnel-plots-an-alternative-to-ranking.html
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!