목표

우리가 그리고자 하는 그래프는 다음과 같은 그래프이다. 에러바가 있는 barplot과 에러바가 있는 lineplot를 그려서 두개를 합치고 A,B로 마킹하는 plot이다.

alt text

데이타 불러오기

이 글에 있는 내용 중 summarySE 함수는 Winston Chang의 R Graphics Cookbook에 있는 내용을 약간 수정한 것임을 밝혀둔다.

먼저 예제에 사용할 데이타는 car 패키지에 있는 Salaries 데이타를 사용하겠다.

require(car)      # 데이타 Salaries 사용하기 위해
require(ggplot2)  # ggplot()을 사용하기 위해
require(plyr)    # ddply() 함수의 사용을 위해

Salaries 데이타는 미국의 조교수,부교수,교수의 월급에 관한 데이타로 모두 397개의 자료이며 한 자료당 6개의 변수가 있다.

str(Salaries)
'data.frame':   397 obs. of  6 variables:
 $ rank         : Factor w/ 3 levels "AsstProf","AssocProf",..: 3 3 1 3 3 2 3 3 3 3 ...
 $ discipline   : Factor w/ 2 levels "A","B": 2 2 2 2 2 2 2 2 2 2 ...
 $ yrs.since.phd: int  19 20 4 45 40 6 30 45 21 18 ...
 $ yrs.service  : int  18 16 3 39 41 6 23 45 20 18 ...
 $ sex          : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 1 ...
 $ salary       : int  139750 173200 79750 115000 141500 97000 175000 147765 119250 129000 ...
head(Salaries)
       rank discipline yrs.since.phd yrs.service  sex salary
1      Prof          B            19          18 Male 139750
2      Prof          B            20          16 Male 173200
3  AsstProf          B             4           3 Male  79750
4      Prof          B            45          39 Male 115000
5      Prof          B            40          41 Male 141500
6 AssocProf          B             6           6 Male  97000
summary(Salaries)
        rank     discipline yrs.since.phd    yrs.service        sex     
 AsstProf : 67   A:181      Min.   : 1.00   Min.   : 0.00   Female: 39  
 AssocProf: 64   B:216      1st Qu.:12.00   1st Qu.: 7.00   Male  :358  
 Prof     :266              Median :21.00   Median :16.00               
                            Mean   :22.31   Mean   :17.61               
                            3rd Qu.:32.00   3rd Qu.:27.00               
                            Max.   :56.00   Max.   :60.00               
     salary      
 Min.   : 57800  
 1st Qu.: 91000  
 Median :107300  
 Mean   :113706  
 3rd Qu.:134185  
 Max.   :231545  

R의 표준 방법

이때 ggplot2에 있는 geom_errorbar 함수를 사용하여 그림을 그릴 수가 있는데 이 함수를 쓰려면 plot을 그리기 전 미리 y축 변수의 표준오차 및 신뢰구간을 구하여야 한다. 표준오차는 표준편차를 표본크기의 제곱근으로 나눈 것이다. 예를 들면 Salaries 자료에서 직급(rank)과 성별(sex)에 따른의 연봉(salary)의 평균, 표준편차, 표준오차를 구하려면 다음과 같이 하면 된다.

df=ddply(Salaries,c("rank","sex"),summarise,mean=mean(salary),sd=sd(salary),n=length(salary),se=sd/sqrt(n))
colnames(df)[3]="salary"
df
       rank    sex    salary        sd   n       se
1  AsstProf Female  78049.91  9371.996  11 2825.763
2  AsstProf   Male  81311.46  7901.343  56 1055.861
3 AssocProf Female  88512.80 17965.286  10 5681.122
4 AssocProf   Male  94869.70 12890.817  54 1754.218
5      Prof Female 121967.61 19619.583  18 4624.380
6      Prof   Male 127120.82 28213.808 248 1791.579

이제 이 함수를 가지고 그림을 그리면 된다. 다음과 같이 하면 된다.

p<-ggplot(df,aes(x=rank,y=salary,fill=sex))
  
p1=p+geom_bar(stat="identity",position="dodge")+
  geom_errorbar(aes(ymin=salary-se,ymax=salary+se),
                position="dodge",width=0.2)
p1

하지만 bar의 위치와 errorbar의 위치가 잘 안맞는다. 그 이유는 geom_bar의 경우 position=“dodge”를 사용하면 position_dodge(0.9)로 변환되지만 geom_error는 position_dodge(0.2)로 바뀌기 때문이다. 따라서 bar의 위치와 error_bar의 위치를 맞추어 주려면 position_dodge(0.9)로 맞추어 주어야 한다.

p2=p+geom_bar(stat="identity",position="dodge")+
  geom_errorbar(aes(ymin=salary-se,ymax=salary+se),
                position=position_dodge(0.9),width=0.2)
p2

하지만 line 그래프의 경우는 다르다. 점과 선으로 된 그래프를 그려보면 다음과 같다.

p3=ggplot(df,aes(x=rank,y=salary,group=sex,color=sex))
p4=p3+geom_point(position="dodge")+
  geom_line(position="dodge")+
  geom_errorbar(aes(ymin=salary-se,ymax=salary+se),
                position="dodge",width=0.2)
p4
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead

geom_point와 geom_line은 position=“dodge”로 지정해도 위치가 바뀌지 않기 때문에 position_dodge(0.2)로 바꾸어 주어야 한다.

p5=p3+geom_point(position=position_dodge(0.2))+
  geom_line(position=position_dodge(0.2))
p5+geom_errorbar(aes(ymin=salary-se,ymax=salary+se),
                position="dodge",width=0.2)
## ymax not defined: adjusting position using y instead
## ymax not defined: adjusting position using y instead

위에서 본 ddply함수를 이용하여 표준오차와 표준편차를 구하는 함수는 문제가 있다. 즉 데이타에 누락값이 있으면 동작하지 않는다. 따라서 그런 점을 개선한 함수는 다음과 같다.

summarySE <- function(data=NULL, measurevar, groupvars=NULL,
                      conf.interval=.95, na.rm=TRUE, .drop=TRUE ) {
  require(plyr)
  # New version of length that can handle NAs: if na.rm==T, don't count them
  length2 <- function (x, na.rm=FALSE) {
    if (na.rm) sum(!is.na(x))
    else       length(x)
  }
  # This does the summary
  datac <- ddply(data, groupvars, .drop=.drop,
                 .fun = function(xx, col, na.rm) {
                   c( n = length2(xx[,col], na.rm=na.rm),
                      mean=mean (xx[,col],na.rm=na.rm),
                      sd = sd   (xx[,col],na.rm=na.rm)
                   )
                 }, 
                 measurevar,
                 na.rm
  )
  # Rename the "mean" column
  #datac
  colnames(datac)[colnames(datac)=="mean"]=measurevar
  #datac <- rename(datac, c("mean" = measurevar))
  datac$se <- datac$sd / sqrt(datac$n)  # Calculate standard error of the mean
  # Confidence interval multiplier for standard error
  # Calculate t-statistic for confidence interval:
  # e.g., if conf.interval is .95, use .975 (above/below), and use
  #  df=n-1, or if n==0, use df=0
  ciMult <- qt(conf.interval/2 + .5, datac$n-1)
  datac$ci <- datac$se * ciMult
  return(datac)
}

이 함수는 다음과 같이 사용하면 된다.

df=summarySE(Salaries,"salary",c("sex","rank"))
df
     sex      rank   n    salary        sd       se        ci
1 Female  AsstProf  11  78049.91  9371.996 2825.763  6296.193
2 Female AssocProf  10  88512.80 17965.286 5681.122 12851.591
3 Female      Prof  18 121967.61 19619.583 4624.380  9756.589
4   Male  AsstProf  56  81311.46  7901.343 1055.861  2115.993
5   Male AssocProf  54  94869.70 12890.817 1754.218  3518.516
6   Male      Prof 248 127120.82 28213.808 1791.579  3528.720

하지만 초보자의 경우 이와 같은 과정을 거쳐 그림을 그리는 것은 무척 어려운 일일 것이다. 따라서 web-r.org에서는 사용자가 ddply함수를 사용하여 데이타를 변환하지 않아도 x축변수, y축변수,group변수, fill변수등을 지정해주고 se, sd자동으로 계산 버튼을 누르면 위와 같은 과정을 거쳐 그래프를 그릴수 있게 해준다.

웹R의 방법

step 1

다음 그림을 보자. web-r.org에 접속하여 로그인 한 후 “웹에서 하는 ggplot2” 샤이니 앱에 들어간 후 잠시 기다린다. default로 Salaries데이타가 선택되어 있다. 표가 보이면 그림과 같이 x축변수, y축변수, fill변수를 선택하고 bar를 클릭하고 stat에는 identity, position은 dodge를 선택한다. 그러면 그림과 같은 errorbar가 없는 barplot이 나온다.

alt text

step 2

그리고 난후 다음 그림과 같이 errorbar 체크박스를 체크하고 sd, se 자동계산버튼을 누른다.

alt text

step 3

그러면 다음과 같은 그래프를 얻는다. 화면을 보면 전처리부분에(preprocessing) 내장되어 있는 summarySE함수를 사용하여 se, sd를 자동으로 구하고 그 데이타프레임을 df에 저장하고 df를 불러들여 에러바가 있는 barplot을 완성한 것을 확인할 수 있다.

alt text

step 4

다음으로 두번째 그래프를 그리기 전에 화면 아래쪽으로 이동해보자. 이 그래프를 그리는데 사용한 R코드와 그래프가 보인다. multiplot으로 저장버튼을 누른다.

alt text

step 5

두번째 그릴 line plot은 x축 변수가 sex이고 rank에 따라 색깔이 달라진다. 먼저 bar 체크박스를 해제하고 x축 변수에 sex를 선택하고 group변수와 color 변수에 rank를 선택하고 point 체크박스를 체크하고 position에 ’dodge(0.3)’을 선택, line 체크박스를 체크하고 position에 ’dodge(0.3)’을 선택한다. 그림이 약간 이상해보이는데 신경쓰지 말자.

alt text

step 6

errorbar 체크박스 아래에 있는 position에 0.3을 입력한다.

alt text

그림이 그려진 것을 확인하고 Multiplot으로 저장버튼을 누른다.

step 7

위쪽의 multiplot 탭을 누른다. 그러면 아래와 같은 화면이 나오는데 plot을 그리는 명령어를 네개 까지 입력할 수 있지만 두개의 plot만 이용한다. 첫번째 plot의 viewport는 default 값이 LUQ(Left Upper Quadrant)로 되어 있다. 즉 화면을 네부분으로 나누었을때 왼쪽 위 사분면에 그림을 넣는다는 뜻이고 두번째 plot은 LLQ 즉 좌하사분면에 위치하게 된다.

alt text

또한 화면 아래부분으로 내려가면 plot download 옵션이라는 부분이 있는데 이곳에서 그림의 넓이, 높이, 해상도 등을 선택할 수 있다.

alt text

step 8

우리는 화면을 세로로 이등분해서 두개의 그림을 위치시킬 것이므로 아래 그림과 같이 첫번째 plot은 left 를 선택하고 두번째 plot은 right 를 선택한다.

alt text

step 9

plot width를 10으로 선택하면 그림의 가로가 길어지게 된다. 그림의 모양을 확인하고 download Multiplot버튼을 눌러서 그림을 다운로드 받으면 된다.

alt text