세그룹 이상의 평균을 비교하는 방법

김종엽




ANOVA라는 이름, 왠지 익숙하신가요? 학부 시절 커리큘럼에 통계 관련 과목이 하나만 있었어도 여러분은 틀림없이 이 단어를 배우셨을 겁니다. 활용 빈도 또한 무척 높죠. 사실 앞 챕터에서 알아봤던 두 그룹의 평균 비교는 논문을 작성할 때 실험군과 대조군의 나이 등을 비교하면서 자연스럽게 녹아들어가고, 실제로 결과 제출에 이용되는 분석 방법은 이 장에서 소개할 세 그룹 이상의 평균 비교부터일 겁니다. 앞장을 잘 이해하셨다면, 절대 어렵지 않습니다. 일단, 두 그룹의 비교에서처럼, 세 그룹 이상의 평균을 비교할 때 사용하는 통계분석방법도 3가지 뿐입니다. 그리고 고르는 방법도 아래 그림처럼 동일한 순서도를 가집니다. 앞장과 유사한 방법으로 진행하면 되겠죠?! 사실 그럴수도 있지만, 이번 챕터에서는 실제 연구에서 늘 부딪치게 되는 데이터 클리닝 과정을 살짝 엿보려고 합니다.

데이터 클리닝(본격적인 분석에 앞서 데이터 정리하기)

이번 챕터에서 이용할 예제 데이터는 건강보험심사평가원에서 공공데이터로 배포했던 대장암 환자 자료 중 300명을 임의로 추출한 것입니다. 데이터 안에는 환자의 나이(age), 성별(sex), 신장(height), 체중(weight), 대장암 병기(stage), 입원일수(HDday), 진단코드(Code) 등이 담겨 있습니다. 먼저 앞에서 배웠던 read.csv()함수를 이용해서 예제 데이터를 불러오도록 하겠습니다.



colon300.csv


> colon300 <- read.csv(file = "colon300.csv", header = TRUE) # 'header = TRUE'라는 
  옵션은 예제데이터의 첫 번째 행이 각 열의 이름이라는 걸 컴퓨터에게 알려줍니다.
> #View(colon300) # 불러들인 colon300.csv파일이 colon300 라는 변수에 잘 담겼는지, 
  새로운 창을 열어 colon300 안을 보여달라는 명령어입니다.

새로운 탭이 열리면서 아래와 같은 화면이 보인다면 성공입니다. 만약 그렇지 않다면, 틀림없이 경로설정의 문제일 겁니다. 이렇게 자신하는 이유는 저도 이 실수를 수도없이 반복하기 때문이죠. working directory가 파일이 위치한 폴더로 설정이 되어 있는지 확인하시기 바랍니다. 아차! 하며 직접 해결하실 수 있는 분들은 아래 결과를 확인한 이후에 계속 진행하시면 되고요. 만약 경로설정에 대해 1도 모르겠다시는 분이라면, 챕터3 ’엑셀파일 csv로 변환해서 R로 불러오기’와 부록 ’파일 경로 마스터하기’를 참고하시기 바랍니다.


데이터를 로드한 이후에 가장 먼저할 일은 어떤 데이터가 로드되었는지 확인하는 일입니다.물론, View()함수를 이용해서 확인하셨지만, 그걸로는 부족합니다. 데이터가 어떤 구조로 구성되어 있는지를 살피는게 진짜죠. 이를테면 심층면접 같은 겁니다. 구조를 보는 함수는 structure라는 단어의 약자인 str()함수입니다. 다음 코드를 입력하시고 Ctr + return(or enter) 키조합을 누르세요.

> str(colon300)
'data.frame':   300 obs. of  7 variables:
 $ age   : int  32 46 63 52 55 53 72 75 64 71 ...
 $ sex   : Factor w/ 2 levels "F","M": 1 1 2 2 2 1 2 1 1 1 ...
 $ height: num  167 167 157 151 165 ...
 $ weight: num  56.7 71.9 49.7 53 50.5 89 54.4 70 55.2 63.8 ...
 $ stage : Factor w/ 4 levels "I","II","III",..: 3 3 3 1 1 2 1 1 1 3 ...
 $ code  : Factor w/ 11 levels "C180","C181",..: 6 7 10 11 7 6 11 9 11 11 ...
 $ HDday : int  8 9 8 11 32 15 19 65 10 8 ...

결과를 살펴보도록 하죠. age는 int 형식으로 38, 52, 62 등등의 값이 담겨있다는 의미입니다. int는 interger의 약자로 정수를 의미합니다. height와 weight도 같은 숫자이지만, 형식은 num인 걸 볼 수가 있습니다. num은 number의 약자로 숫자를 의미합니다. int와는 달리 소숫점 아래의 숫자가 담을 수 있습니다. sex와 stage, code는 Factor라고 표시되어 있는데요. 한글로는 ’요인’이라고 번역합니다. 처음에는 문자가 담기는 chr형식과 혼돈스러우실 겁니다. 둘다 문자가 담기니까요. 하지만, chr에는 개별 문자가 모두 고유명사처럼 쓰인다면, 개별의 의미를 가진다면, Factor에서 문자는 종류(level) 중의 하나를 의미합니다. 예를 들어, sex는 2개의 levels “F”와 “M”으로 구성되어 있다는 의미이고, stage는 4개의 요인으로 구성되어 있으며, 개별 행은 4개의 요인 중 하나를 가지게 되죠. code는 11개로 구성되어 있음을 알 수 있습니다.

추가설명 : Factor w/4 levels “I”는 이 행은 4개 요인 중 하나인 ’I’값을 가진다는 걸 의미합니다. 단순히 ’I’라는 이름이 아니라, 요인 중 하나라는 의미는 R프로그램 뿐 아니라, 모든 통계 관련 프로그램에서 굉장히 큰 의미를 가집니다. 그러니, str()함수를 통해 데이터셋의 구조를 볼 때 해당열이 Factor인지 아니면 chr인지 구별해서 보는 실력을 키우셔야 합니다.

결측값(비어 있는 값)을 제거하기

실습을 위해 제작한 데이터셋을 제외하고 결측값이 하나도 없는 데이터는 존재하지 않습니다. 세상일이 그렇게 단순하지 않으니까요. View(colon300) 명령어를 통해 열어놓은 탭을 클릭해서 raw 데이터를 살펴보시면, 11번 째 환자 데이터의 경우 height 항목에 NA라고 표시되어 있는 걸 보실 수 있습니다. NA(또는 na)는 컴퓨터에서 값이 비어 있다는 의미입니다. ’0’과는 또다른 의미죠. 그런데 이런 값들이 통계분석에 그대로 포함되면 현상을 왜곡시킬 수가 있습니다. 그래서 연구자들은 크게 2가지 방법을 많이 활용합니다. 하나는 그 주변 행의 값들을 가지고 유추해서 결측값을 채우는 방법입니다. 두 번째 방법은 행(환자)에 하나의 값이라도 결측값(누락된 결과값)이 있으면 아예 그 행(환자)을 전체데이터셋에서 삭제하는 방법입니다. 저는 두 번째 방법을 선호합니다. 그런데 전체 환자 수가 만 명 단위를 넘어서면 수작업으로 결측값이 포함된 행(환자)을 모두 선별한다는 건 매우 어려운 일입니다. 그래서 결측값이 포함된 모든 행(환자)을 자동으로 제거해주는 함수가 있습니다. 바로 na.omit()이라는 함수입니다. 해당 함수를 써서, colon300 데이터셋에서 결측값이 하나도 없는 환자만을 추려 colon_clean이라는 변수에 담아보도록 하겠습니다.

> colon_clean <- na.omit(colon300)