Pie plot과 Donut plot의 결합
문건웅
2016년 5월 8일
목표
일반적으로 파이그래프는 자료를 표현하는데 있어 그리 좋은 방법은 아닌 것으로 알려져 있다. 특히 자료의 갯수가 많아 질 경우 파이그래프보다 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 데이타를 이용하여 진단명과 흡연여부를 나타내보면 다음과 같다.
일반적으로 파이그래프는 자료를 표현하는데 있어 그리 좋은 방법은 아닌 것으로 알려져 있다. 특히 자료의 갯수가 많아 질 경우 파이그래프보다 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 데이타를 이용하여 진단명과 흡연여부를 나타내보면 다음과 같다.
Donut plot 의 구현
먼저 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
먼저 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
Pie Plot
먼저 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
먼저 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의 결합
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에 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
Dount plot의 개선
이 그림과 실제 저자가 만들어 사용하는 그림은 몇가지 차이가 있다. 먼저 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
이 그림과 실제 저자가 만들어 사용하는 그림은 몇가지 차이가 있다. 먼저 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
PieDonut 의 개선
처음 저자가 목표로 보여준 plot은 먼저 browser의 종류에 따라 색깔이 정해지고 그색깔을 기준으로 version의 색깔이 바뀐다. 또한 원형좌표계의 시작이 0도 지점이 아니고 270도 지점이다. ggPieDonut()함수는 다음과 같이 쓸 수 있다.
ggPieDonut(browsers,"browser","version","share")
ggPieDonut(acs,"Dx","smoking")
ggPieDonut(mtcars,"cyl","carb")
ggPieDonut() 함수를 각자 만들어보시기 바란다. 제일 먼저 웹R의 게시판에 글 올려주신 분에게는 저자가 곧 출판할 신간(영문책)을 한권 보내드리도록 하겠다.
처음 저자가 목표로 보여준 plot은 먼저 browser의 종류에 따라 색깔이 정해지고 그색깔을 기준으로 version의 색깔이 바뀐다. 또한 원형좌표계의 시작이 0도 지점이 아니고 270도 지점이다. ggPieDonut()함수는 다음과 같이 쓸 수 있다.
ggPieDonut(browsers,"browser","version","share")
ggPieDonut(acs,"Dx","smoking")
ggPieDonut(mtcars,"cyl","carb")
ggPieDonut() 함수를 각자 만들어보시기 바란다. 제일 먼저 웹R의 게시판에 글 올려주신 분에게는 저자가 곧 출판할 신간(영문책)을 한권 보내드리도록 하겠다.
Comment 2
- Total
- 의학논문 작성을 위한 R통계와 그래프
- R을 이용한 조건부과정분석
- 웹에서 클릭만으로 하는 R통계분석
- Learn ggplot2 Using Shiny App
- 일반화가법모형 소개
- 밑바닥부터 시작하는 ROC 커브 분석
- 웹R을 이용한 통계분석
- 의료인을 위한 R 생존분석
No. | Subject | Author | Date |
---|---|---|---|
25 | 2판 출판 예정일 문의 [2] | pslee | 2024.01.23 |
24 | 2판 혹시 언제쯤 출간 예정일지요? [1] | 니콜라오 | 2023.10.13 |
23 | 2판 [1] | rlagurrn | 2023.01.27 |
22 | mytable 문의 [2] | 떠도는고라니 | 2022.12.20 |
21 | 제2판 출간소식을 기다립니다.. [1] | swpapa | 2021.04.05 |
20 | 책 구매 하려고 하는데 품절이 되서 구매할수 있는지 궁금합니다. [1] | 기드온 | 2020.07.30 |
19 | 메타분석 강의록 | cardiomoon | 2020.05.31 |
18 | 설문조사데이터 | cardiomoon | 2020.05.08 |
17 | 데이터 전처리 예제 | cardiomoon | 2020.05.08 |
16 | moonbook package 설치에 문제가 있는 건가요? [2] | KCRS_LeeJM | 2017.03.14 |
15 | 해결되지 않는 레이텍, ztable, moonbook2에 대해 질문 드립니다. [1] | neurojang | 2017.01.04 |
14 | Interactive plot with ggplot2 and ggiraph [1] | cardiomoon | 2016.05.25 |
13 | ggBidirectionalBar.R | cardiomoon | 2016.05.22 |
12 | 인구피라미드 : Bidirectional Barplot | cardiomoon | 2016.05.22 |
11 | Radar Chart | cardiomoon | 2016.05.20 |
10 | ggRadar.R | cardiomoon | 2016.05.20 |
9 | Rose plot with ggplot2 [1] | cardiomoon | 2016.05.10 |
» | Pie plot과 Donut plot의 결합 [2] | cardiomoon | 2016.05.08 |
7 | 책에 있는 R code 만 추출한 R 파일입니다. [1] | cardiomoon | 2016.05.03 |
6 | 교재 예제자료 [2] | 통계마술사 | 2016.01.18 |
좋은 자료 감사합니다.
그래프가 정말 보기 좋네요. 정말 잘 만들어진 것 같습니다.