막대 그래프는 가장 많이 사용되는 그래프 중 하나이다. car 패키지에 포함되어 있는 Salaries 데이타는 2008-9년 미국의 한 대학교의 직급과 연봉에 관한 데이타이다. 이 데이터에서 성별에 따른 직급 분포를 barplot으로 그려보면 다음과 같다.
require(car)
require(ggplot2)
require(ggiraph)
require(moonBook)
ggplot(Salaries,aes(x=sex,fill=rank))+geom_bar()
이를 proportional stacked bar plot을 그려보면 다음과 같이 할 수 있다.
ggplot(Salaries,aes(x=sex,fill=rank))+geom_bar(position="fill")
이 그래프의 단점은 Male과 Female의 전체 인원수 가 다른데 비율만을 보여주기 때문에 성별에 따른 분포를 표현할 수 없다는 점이다. R의 기본패키지인 graphics에 포함되어 있는 spineplot은 bar의 width가 각각 다른 proportional bar plot을 그려준다.
par(mfrow=c(1,2))
spineplot(rank~sex,data=Salaries)
spineplot(sex~rank,data=Salaries)
par(mfrow=c(1,1))
저자는 ggplot2와 ggiraph 패키지를 이용하여 spine plot을 그려주는 ggSpine()함수를 만들어 보았다. spineplot과 유사하지만 Interaction이 가능한 것이 장점이다.
source("ggSpine.R")
ggSpine(data=Salaries,"rank","sex",interactive=TRUE)
addlabel=TRUE로 주면 label을 자동으로 붙여준다.
ggSpine(data=Salaries,"sex","rank",addlabel = TRUE,interactive=TRUE)
geom_bar()와 마찬가지로 position=“stack” 또는 position=“dodge”도 쓸수 있다.
ggSpine(data=Salaries,"sex","rank",position="stack",addlabel = TRUE,interactive=TRUE)
ggSpine(data=Salaries,"sex","rank",position="dodge",addlabel = TRUE,interactive=TRUE)
이 함수는 데이타를 집계하여 그래프를 그릴 수도 있고 이미 count되어 있는 데이타로 그래프를 그릴 수도 있다. 지난번 저자가 rose plot을 올릴 때 사용한 데이타로 Rose plot을 그리려면 다음과 같다.
rose=read.csv("rose.csv",stringsAsFactors = FALSE)
rose$Month=factor(rose$Month,levels=month.name)
rose$tooltip=paste0(rose$Month,"<br>",rose$group,"<br>",rose$value)
rose$data_id=as.character(1:nrow(rose))
p<-ggplot(rose,aes(x=Month,fill=group,y=value))+
geom_bar_interactive(aes(data_id=data_id,tooltip=tooltip),stat="identity",width=1,color="black",size=0.1)+
scale_fill_brewer(palette="Greens")+coord_polar()
tooltip_css <- "background-color:white;font-style:italic;padding:10px;border-radius:20px 20px 20px 20px;"
ggiraph(code={print(p)},tooltip_extra_css = tooltip_css)
이 그림은 각 월별로 A-G까지의 합계가 다른 점을 표현하지 못하고 있다. 이를 ggSpine()함수로 표현해보면 다음과 같다. count가 되어 있는 자료의 경우 stat=“identity”로 지정하고 count가 있는 열이름을 yvar로 지정하여야 한다. 또한 bar사이의 간격을 없애려면 width=1로 한다.
rose1=read.csv("rose.csv",stringsAsFactors = FALSE)
rose1
group Month value
1 A January 10.0
2 B January 9.0
3 C January 8.0
4 D January 7.0
5 E January 6.0
6 F January 5.0
7 G January 4.0
8 A February 5.0
9 B February 4.5
10 C February 4.0
11 D February 3.5
12 E February 3.0
13 F February 2.5
14 G February 2.0
15 A March 7.0
16 B March 6.0
17 C March 5.0
18 D March 4.0
19 E March 3.0
20 F March 2.0
21 G March 2.0
22 A April 9.0
23 B April 7.0
24 C April 8.0
25 D April 7.0
26 E April 6.0
27 F April 5.0
28 G April 4.0
29 A May 11.0
30 B May 8.0
31 C May 4.0
32 D May 3.5
33 E May 3.0
34 F May 2.5
35 G May 2.0
36 A June 13.0
37 B June 9.0
38 C June 5.0
39 D June 4.0
40 E June 3.0
41 F June 2.0
42 G June 2.0
43 A July 15.0
44 B July 10.0
45 C July 8.0
46 D July 7.0
47 E July 6.0
48 F July 5.0
49 G July 4.0
50 A August 17.0
51 B August 11.0
52 C August 4.0
53 D August 3.5
54 E August 3.0
55 F August 2.5
56 G August 2.0
57 A September 19.0
58 B September 12.0
59 C September 5.0
60 D September 4.0
61 E September 3.0
62 F September 2.0
63 G September 2.0
64 A October 21.0
65 B October 13.0
66 C October 8.0
67 D October 7.0
68 E October 6.0
69 F October 5.0
70 G October 4.0
71 A November 23.0
72 B November 14.0
73 C November 4.0
74 D November 3.5
75 E November 3.0
76 F November 2.5
77 G November 2.0
78 A December 25.0
79 B December 15.0
80 C December 5.0
81 D December 4.0
82 E December 3.0
83 F December 2.0
84 G December 2.0
rose1$Month=factor(rose1$Month,levels=month.name)
p<-ggSpine(rose1,"group","Month",yvar="value",stat="identity",width=1)
ggiraph(code={print(p)})
이것을 polar map으로 바꾸려면 polar=TRUE를 지정해주면 된다.
p<-p+coord_polar()
ggiraph(code={print(p)})
위의 코드는 다음의 코드와 동일하다.
ggSpine(rose1,"group","Month",yvar="value",stat="identity",
width=1,polar=TRUE,interactive=TRUE)
geom_bar()와 유사하게 position=“stack” 으로 바꾸어주면 varaible width의 stacked bar plot을 얻을 수 있다.
ggSpine(rose1,"group","Month",yvar="value",stat="identity",
position="stack",width=1,interactive=TRUE)
이 때도 polar=TRUE를 주면 variable width의 rose plot을 얻을 수 있다.
ggSpine(rose1,"group","Month",yvar="value",stat="identity",polar=TRUE,
position="stack",width=1,interactive=TRUE)
stat=“identity”를 쓰지 않으면 각각의 자료의 갯수를 count하므로 다음과 같은 plot을 얻는다.
ggSpine(rose1,"group","Month",yvar="value",
width=1,polar=TRUE,interactive=TRUE)
사실 ggSpine() 함수의 강력함은 연속형변수에 적용할 때 histogram과 비슷한 기능을 한다는 점이다. 이때 x축 라벨이 겹치지 않게 하기 위해 열합계가 전체의 4%가 되지 않는 열은 출력하지 않는다.
ggSpine(Salaries,"rank","yrs.service",interactive=TRUE)
addlabel= TRUE 로 하면 라벨을 붙여주는데 겹치는 것을 막기 위해 열합계가 전체의 4%가 되지 않는 열은 라벨을 출력하지 않는다.
ggSpine(Salaries,"rank","yrs.service",addlabel=TRUE,interactive=TRUE)
또 다른 예로써 ggSpine()함수를 그냥 호출하면 moonBook패키지의 acs데이타 중에서 smoking과 age의 관계를 보여준다.
ggSpine(addlabel=TRUE,interactive=TRUE)
smoking과 콜레스테롤의 관계를 보려면 다음과 같이 할 수 있다. 이 때 팔레트를 바꾸고 싶은 경우 다음과 같이 할수 있다.
ggSpine(data=acs,"smoking","TC",addlabel=TRUE,palette="Reds",interactive=TRUE)
이와 같이 ggplot2와 ggiraph패키지를 만들어 사용한 함수들은 htmlwidgets패키지의 saveWidget()함수를 사용하여 html파일로 만들어 local computer에 저장할 수도 있고 그 ㅊ파일을 파워포인트 파일 내에서 링크를 걸어 프리젠테이션에도 사용할 수 있다. 다음과 같이 하면 된다.
require(htmlwidgets)
p<-ggSpine(data=acs,"smoking","TC",addlabel=TRUE,palette="Reds",interactive=TRUE)
saveWidget(p,"ggSpine.html")
ggSpine()함수를 만드는데 꼬박 48시간이 걸렸다. ggSpine()함수의 소스는 시간이 허락하는대로 패키지로 만들어 공개할 예정이며 web-r.org에서 클릭만으로 사용하고 다운로드받을 수 있도록 할 예정이다.