일반적으로 파이그래프는 자료를 표현하는데 있어 그리 좋은 방법은 아닌 것으로 알려져 있다. 특히 자료의 갯수가 많아 질 경우 파이그래프보다 donut 그래프가 더 좋은 것으로 알려져 있다. 이번 글의 목표는 파이그래프와 donut plot을 결합하여 보기 좋은 그래프를 만드는 것이다. 다음과 같은 자료가 있다고 하자.
browsers=read.csv("browsers.csv")
browsers
browser version share
1 MSIE MSIE 6.0 10.85
2 MSIE MSIE 7.0 7.35
3 MSIE MSIE 8.0 33.06
4 MSIE MSIE 9.0 2.81
5 Firefox Firefox 3.5 1.58
6 Firefox Firefox 3.6 13.12
7 Firefox Firefox 4.0 5.43
8 Chrome Chrome 10.0 9.91
9 Safari Safari 4.0 1.42
10 Safari Safari 5.0 4.55
11 Opera Opera 11.x 1.65
이때 이 자료를 이용하여 다음과 같은 그래프를 그리고자 한다.
또는 필자가 만든 moonBook package에 있는 acs 데이타를 이용하여 진단명과 흡연여부를 나타내보면 다음과 같다.
먼저 Pie plot과 Donut plot을 비교해보자. ggplot2의 geom_rect()및 coord_polar()를 이용하면 간단하게 그릴 수 있다. geom_rect()를 이용하려면 ymin, ymax, xmin, xmax 좌표를 지정해주어야 한다. 이를 위하여 먼저 다음과 같이 자료를 전처리한다.
dat1<-browsers
dat1$ymax<-cumsum(dat1$share)
dat1$ymin<-cumsum(dat1$share)-dat1$share
dat1$ypos<-dat1$ymin+dat1$share/2
dat1$ratio<-dat1$share*100/sum(dat1$share)
dat1
browser version share ymax ymin ypos ratio
1 MSIE MSIE 6.0 10.85 10.85 0.00 5.425 11.828191
2 MSIE MSIE 7.0 7.35 18.20 10.85 14.525 8.012646
3 MSIE MSIE 8.0 33.06 51.26 18.20 34.730 36.040554
4 MSIE MSIE 9.0 2.81 54.07 51.26 52.665 3.063338
5 Firefox Firefox 3.5 1.58 55.65 54.07 54.860 1.722446
6 Firefox Firefox 3.6 13.12 68.77 55.65 62.210 14.302845
7 Firefox Firefox 4.0 5.43 74.20 68.77 71.485 5.919546
8 Chrome Chrome 10.0 9.91 84.11 74.20 79.155 10.803445
9 Safari Safari 4.0 1.42 85.53 84.11 84.820 1.548021
10 Safari Safari 5.0 4.55 90.08 85.53 87.805 4.960209
11 Opera Opera 11.x 1.65 91.73 90.08 90.905 1.798757
먼저 geom_rect()를 이용하여 막대그래프를 만들어보자.
require(ggplot2)
p<-ggplot(dat1)+geom_rect(aes(xmin=3,xmax=4,ymin=ymin,ymax=ymax,fill=version))
p
이제 coord_polar()를 이용하여 좌표계를 원형좌표계로 변환한다. 양궁에서 쓰이는 과녁과 비슷한 Buul’s eye plot이 그려진다.
p+coord_polar()
이를 Pie plot으로 변환하려면 coord_polar의 theta옵션을 “y”로 주면 된다.
p+coord_polar(theta="y")
이 그래프를 Donut plot으로 바꾸는 것은 x축의 좌표의 범위만 바꾸어 주면 된다.
p+coord_polar(theta="y")+xlim(0,4)
범례를 없애고 대신 browser version을 각 모형에 표시하면 다음과 같다.
p<-p+coord_polar(theta="y")+xlim(0,4)+
geom_text(aes(x=3.5,y=ypos,label=version))+
guides(fill=FALSE)
p
좌표계 축 및 라벨을 제거하기 위해 다음과 같은 테마를 만들어 사용하였다.
theme_clean=function(base_size=12){
theme_grey(base_size) %+replace%
theme(
axis.title=element_blank(),
axis.text=element_blank(),
panel.background=element_blank(),
panel.grid=element_blank(),
axis.ticks.length=unit(0,"cm"),
axis.ticks.margin=unit(0,"cm"),
panel.margin=unit(0,"lines"),
plot.margin=unit(c(0,0,0,0),"lines"),
complete=TRUE
)
}
theme_axis_blank=function(){
theme(axis.ticks=element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank())
}
p<-p+theme_clean()
p
Donut plot에 Pie plot을 다음과 같이 결합할 수 있다. 먼저 pie plot을 그리기 위한 데이타 전처리가 필요하다.
dat1
browser version share ymax ymin ypos ratio
1 MSIE MSIE 6.0 10.85 10.85 0.00 5.425 11.828191
2 MSIE MSIE 7.0 7.35 18.20 10.85 14.525 8.012646
3 MSIE MSIE 8.0 33.06 51.26 18.20 34.730 36.040554
4 MSIE MSIE 9.0 2.81 54.07 51.26 52.665 3.063338
5 Firefox Firefox 3.5 1.58 55.65 54.07 54.860 1.722446
6 Firefox Firefox 3.6 13.12 68.77 55.65 62.210 14.302845
7 Firefox Firefox 4.0 5.43 74.20 68.77 71.485 5.919546
8 Chrome Chrome 10.0 9.91 84.11 74.20 79.155 10.803445
9 Safari Safari 4.0 1.42 85.53 84.11 84.820 1.548021
10 Safari Safari 5.0 4.55 90.08 85.53 87.805 4.960209
11 Opera Opera 11.x 1.65 91.73 90.08 90.905 1.798757
data2=ddply(dat1,"browser",summarize,sum(share))
colnames(data2)[2]="sum"
data2=data2[order(data2$sum,decreasing=TRUE),]
data2$cumsum=cumsum(data2$sum)
data2$pos=data2$cumsum-data2$sum/2
data2$ymin=data2$cumsum-data2$sum
data2$ratio=data2$sum*100/sum(data2$sum)
data2
browser sum cumsum pos ymin ratio
3 MSIE 54.07 54.07 27.035 0.00 58.944729
2 Firefox 20.13 74.20 64.135 54.07 21.944838
1 Chrome 9.91 84.11 79.155 74.20 10.803445
5 Safari 5.97 90.08 87.095 84.11 6.508231
4 Opera 1.65 91.73 90.905 90.08 1.798757
이제 이렇게 만들어진 data2를 이용하여 기존의 plot에 파이그래프를 덧그린다.
p<-p+geom_rect(data=data2,aes(xmin=0,xmax=3,ymin=ymin,ymax=cumsum,fill=browser))+
geom_text(data=data2,aes(x=1.5,y=pos,label=browser))
p
이 그림과 실제 저자가 만들어 사용하는 그림은 몇가지 차이가 있다. 먼저 donut plot의 라벨이 plot의 밖에 있고 선으로 연결되어 있다. 이 그림을 위해 저자가 만든 함수는 다음과 같다.
ggDonut=function(data=acs,donuts="Dx",count=NULL,
addPieLabel=TRUE,addDonutLabel=TRUE,showRatio=TRUE,
polar=TRUE,labelposition=1){
if(is.null(count)){
dat1=ddply(data,donuts,nrow)
colnames(dat1)[2]="n"
} else{
dat1=data
colnames(dat1)[colnames(dat1)==count]="n"
}
dat1$ymax=cumsum(dat1$n)
dat1$ymin=cumsum(dat1$n)-dat1$n
dat1$ypos=dat1$ymin+dat1$n/2
dat1$ratio=dat1$n*100/sum(dat1$n)
dat1$cumratio=dat1$ypos*100/sum(dat1$n)
dat1$hjust=ifelse((dat1$cumratio>25 & dat1$cumratio<75),0,1)
mainCol=rainbow(nrow(dat1))
p<-ggplot(dat1) +
geom_rect(aes( ymax=ymax, ymin=ymin, xmax=4,xmin=3),fill=mainCol,
colour="white",alpha=0.7)+
coord_polar(theta="y",start=3*pi/2)+
xlim(0,4+labelposition)+
theme_clean()
label=dat1[[donuts]]
if(showRatio)
label=paste0(label,"\n(",round(dat1$ratio,1),"%)")
if(labelposition==1) {
p<- p+ geom_text(aes(label=label,x=4.3,y=ypos,hjust=hjust),size=3)+
geom_segment(aes(x=4,xend=4.2,y=ypos,yend=ypos))
} else{
p<- p+ geom_text(aes(label=label,x=3.5,y=ypos),size=3)
}
p
}
사용하는 방법은 아주 간단하다. browser 자료는 “share”라는 열에 데이타가 있다.
ggDonut(browsers,"version","share")
Warning: `axis.ticks.margin` is deprecated. Please set `margin` property of
`axis.text` instead
ggDonut(browsers,"version","share",labelposition=0)
Warning: `axis.ticks.margin` is deprecated. Please set `margin` property of
`axis.text` instead
mtcars데이타에서 엔진 수에 따른 분포를 보려면 다음과 같이 할 수 있다.
ggDonut(mtcars,"cyl")
Warning: `axis.ticks.margin` is deprecated. Please set `margin` property of
`axis.text` instead
처음 저자가 목표로 보여준 plot은 먼저 browser의 종류에 따라 색깔이 정해지고 그색깔을 기준으로 version의 색깔이 바뀐다. 또한 원형좌표계의 시작이 0도 지점이 아니고 270도 지점이다. ggPieDonut()함수는 다음과 같이 쓸 수 있다.
ggPieDonut(browsers,"browser","version","share")
ggPieDonut(acs,"Dx","smoking")
ggPieDonut(mtcars,"cyl","carb")
ggPieDonut() 함수를 각자 만들어보시기 바란다. 제일 먼저 웹R의 게시판에 글 올려주신 분에게는 저자가 곧 출판할 신간(영문책)을 한권 보내드리도록 하겠다.