使用ggplot2绘制饼图

在之前的一系列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

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

p + coord_polar(theta = 'y')

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

#绘制条形宽度为1的条形图

p <- ggplot(data = df, mapping = aes(x = 'Content', y = nums, fill = type)) + geom_bar(stat = 'identity', position = 'stack', width = 1)

p

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

#绘制无空心点的饼图

p + coord_polar(theta = 'y')

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

#这里的标签其实就是坐标轴的标签,可以通过labs()函数将其清除

p + coord_polar(theta = 'y') + labs(x = '', y = '', title = '')

0?wx_fmt=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())

0?wx_fmt=png
这里的刻度值清除了。

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

0?wx_fmt=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)

0?wx_fmt=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") 

0?wx_fmt=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)) 

0?wx_fmt=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)) 

0?wx_fmt=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)) 

0?wx_fmt=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))

0?wx_fmt=png

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

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


参考资料

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

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值