使用ggplot2绘制饼图

浏览: 2362

在之前的一系列gglot2绘制条形图、折线图和散点图后,有网友问如何使用ggplot2绘制饼图。其实ggplot2并没有类似于geom_pie()这样的函数实现饼图的绘制,但ggplot2有一个理念,就是通过极坐标变换绘制饼图,下文就教大家一步步绘制精美的饼图。

饼图在ggplot2中就是通过极坐标变换获得,在绘制饼图之前需要绘制堆叠的条形图,通过将条形图进行极坐标变换后,就能实现饼图绘制了。

library(ggplot2)
type <- c('A','B','C','D','E','F','G')
nums <- c(10,23,8,33,12,40,60)
df <- data.frame(type = type, nums = nums)
#绘制条形图
p <- ggplot(data = df, mapping = aes(x = 'Content', y = nums, fill = type)) + geom_bar(stat = 'identity', position = 'stack')
p

image.png

#堆叠的条形图绘制完后,接下来就需要进行极坐标变换了,ggplot2中coord_polar()函数可以非常方便的实现极坐标变换。
p + coord_polar(theta = 'y')

image.png
发现饼图中间有一个空心圆,这有点不像常见的饼图啊,不急,这里只需稍稍改动原条形图的宽度就可以啦,这里将宽度设置为1

#绘制条形宽度为1的条形图
p <- ggplot(data = df, mapping = aes(x = 'Content', y = nums, fill = type)) + geom_bar(stat = 'identity', position = 'stack', width = 1)
p

image.png
看见与之前的条形图之间的区别了吗?对,两边的空隙不见了。

#绘制无空心点的饼图
p + coord_polar(theta = 'y')

image.png
好,一个完整的饼图绘制完了,咦?饼图周围还有多余的数字(0,50,100,150)、标签(“Content”,nums)、刻度(Content)和横杠(-),这我该如何清除呢?

#这里的标签其实就是坐标轴的标签,可以通过labs()函数将其清除。
p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '')

image.png
很好,标签(“Content”,nums)已经被清除了,那起眼的刻度值(Content)、(0,50,100,150)和横杠(-)又该如何清除呢?其实刻度(Content)、(0,50,100,150)和横杠(-)在原条形图中就是x轴和y轴的刻度值及刻度标记,可以通过theme()的方法将他们清除掉

p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank())

image.png
这里的刻度值清除了。

p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank())

image.png
这里的刻度标记也清除了。

大功告成,一个饼图就这样一步步实现了。有人会问,你这个饼图蛮好看的,就是有一点不好,我不知道各个部分各占多少百分比啊。这是一个非常好的问题,接下来就看看如何给这个饼图绘制百分比。

第一种方法,将百分比直接显示在图例中,这种方式适合分类较多的情况。

#先来看看如何将这样的百分比(10.2%)表示出来
label_value <- paste('(', round(df$nums/sum(df$nums) * 100, 1), '%)', sep = '')
label_value

[1] "(5.4%)"  "(12.4%)" "(4.3%)"  "(17.7%)" "(6.5%)"  "(21.5%)"

[7] "(32.3%)"

#下面还需要为这些百分比值对应到各个组。
label <- paste(df$type, label_value, sep = '')
label

[1] "A(5.4%)"  "B(12.4%)" "C(4.3%)"  "D(17.7%)" "E(6.5%)"  "F(21.5%)"

[7] "G(32.3%)"

好!接下来就是将这些百分比标签放到图例中。

p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank()) + scale_fill_discrete(labels = label)

image.png
Perfect!非常完美,百分比标签就这样上去了。

第二种方法,直接将百分比放到各自的饼区中。

#首先去掉图例
p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank()) + theme(legend.position = "none") 

image.png

#通过计算极坐标中x和y轴的位置,将标签贴在相应的地方。
p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank()) + theme(legend.position = "none") + geom_text(aes(y = df$nums/2 + c(0, cumsum(df$nums)[-length(df$nums)]), x = sum(df$nums)/150, label = label)) 

image.png
这里需要说明的是,x = sum(df$nums)/150是需要不断调整的,分母越小,标签离饼图越远,分母越大,标签月挤到一起。下面放两个特例:

p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank()) + theme(legend.position = "none") + geom_text(aes(y = df$nums/2 + c(0, cumsum(df$nums)[-length(df$nums)]), x = sum(df$nums)/50, label = label)) 

image.png


p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank()) + theme(legend.position = "none") + geom_text(aes(y = df$nums/2 + c(0, cumsum(df$nums)[-length(df$nums)]), x = sum(df$nums)/300, label = label)) 

image.png
有人还想问,可不可以绘制环形图呀?没问题啊,当然可以,只需将条形图的宽度调整到小于1就可以了,还记得之前的第一张饼图中间有一个空心白圈吗?就是因为默认的条形宽度为0.9导致的。

ggplot(data = df, mapping = aes(x = 'Content', y = nums, fill = type)) + geom_bar(stat = 'identity', position = 'stack', width = 0.5) + coord_polar(theta = 'y') + labs(x = '', y = '', title = '') + theme(axis.text = element_blank()) + theme(axis.ticks = element_blank()) + theme(legend.position = "none") + geom_text(aes(y = df$nums/2 + c(0, cumsum(df$nums)[-length(df$nums)]), x = sum(df$nums)/180, label = label))

image.png

简单吧,真心的小凯斯啊~

对于饼图的绘制就说到这里,如果你想绘制3D饼图,ggplot2就不是一个很好的选择,因为其目前还无法实现3D功能。


参考资料

http://www.bubuko.com/infodetail-1036150.html


每天进步一点点2015

学习与分享,取长补短,关注小号!

image.png




推荐 1
本文由 每天进步一点点2015 创作,采用 知识共享署名-相同方式共享 3.0 中国大陆许可协议 进行许可。
转载、引用前需联系作者,并署名作者且注明文章出处。
本站文章版权归原作者及原出处所有 。内容为作者个人观点, 并不代表本站赞同其观点和对其真实性负责。本站是一个个人学习交流的平台,并不用于任何商业目的,如果有任何问题,请及时联系我们,我们将根据著作权人的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。

0 个评论

要回复文章请先登录注册