R语言绘制好看的饼图、空心饼图

时间:2024-12-11 07:21:37

饼图或者说扇形图在统计分析结果展示中非常常用,R语言自带做饼图的函数pie,做起来非常简单,只需提供比例,样品名称即可。


#构建数据
ratio <- c(24.2, 21.9, 7.6, 5.2,4.3,3.2,2.6,2.6,1.8,1.8,24.8)
disease <- c("Heart disease", "Cancer","injuries", "CPD",
             "Stroke",'Type2 diabetes',"AD","Suicide",
             "IP","Chronic liver disease","Other")

pie(ratio, labels=disease,
    radius = 1.0,clockwise=T,
    main = "Male individuals")

默认的颜色只有6中,循环使用的,不过这个颜色可以自定义。


#自定义颜色
colors <-c('#E5D2DD', '#53A85F', '#F1BB72', '#F3B1A0', 
           '#D6E7A3', '#57C3F3', '#476D87',
           '#E59CC4', '#AB3282', '#23452F', '#BD956A')
pie(ratio, labels=disease,
    radius = 1.0,clockwise=T,
    col = colors,
    main = "Male individuals")

用pie作图其实就够了,但奈何很“卷”,有其他好看的饼图,所以接下来还是结合ggplot2与ggforce做可以变换的饼图,例如空心饼图。单独用ggplot2作图比较繁琐,不建议去尝试了,太费时间没必要。

先做一个基本的饼图。


A <- (ratio, disease)#构建一个数据框
library(ggplot2)
library(ggforce)

ggplot()+
  theme( = element_blank(),
         = element_blank(),
         = element_blank(), 
         = element_blank(),
         = element_blank(),
        =element_blank(), 
         = element_blank(),
         = element_blank())+#去除没用的ggplot背景,坐标轴
  xlab("")+ylab('')+#添加颜色
  scale_fill_manual(values = c('#E5D2DD', '#53A85F', '#F1BB72', '#F3B1A0', 
                               '#D6E7A3', '#57C3F3', '#476D87',
                               '#E59CC4', '#AB3282', '#23452F', '#BD956A'))+
  geom_arc_bar(data=A,
               stat = "pie",
               aes(x0=0,y0=0,r0=0,r=2,
                   amount=ratio,fill=disease)
  )+#饼图
  annotate("text",x=1.6,y=1.5,label="24.20%",angle=-50)+
  annotate("text",x=1.6,y=-1.5,label="21.9%",angle=45)+
  annotate("text",x=0,y=-2.2,label="7.6%",angle=0)+
  annotate("text",x=-0.8,y=-2,label="5.2%",angle=-20)+
  annotate("text",x=-1.3,y=-1.7,label="4.3%",angle=-40)+
  annotate("text",x=-1.6,y=1.5,label="24.8%",angle=45)#手动注释,还是很麻烦

要想得到空心饼图,只需要将geom_arc_bar参数中r0改为1即可。


geom_arc_bar(data=A,
               stat = "pie",
               aes(x0=0,y0=0,r0=1,r=2,
                   amount=ratio,fill=disease))

想要分割饼图,geom_arc_bar中添加explode参数。


geom_arc_bar(data=A,
               stat = "pie",
               aes(x0=0,y0=0,r0=1,r=2,
                   amount=ratio,fill=disease,
                   explode=c(0.05,0.1,0.05,0.05,
                             0.05,0.05,0.05,0.05,0.05,0.1,0.1))
  )

可以发现,以上作图有一个bug就是添加比例标记很麻烦,要想实现自动化需要编写函数很麻烦。参考:/questions/52960015/how-to-avoid-label-overlap-in-pie-chart。可以先将每个标签角度计算好,再添加,结果还好。

ratio <- c(24.2, 21.9, 7.6, 5.2,4.3,3.2,2.6,2.6,1.8,1.8,24.8)
disease <- c("Heart disease", "Cancer","injuries", "CPD",
             "Stroke",'Type2 diabetes',"AD","Suicide",
             "IP","Chronic liver disease","Other")
Group <- c("male","male","male","male","male","male",
           "male","male","male","male","male")
A <- (Group, disease,ratio)
#添加角度
A_pies4 <- left_join(A,
 A %>%
 group_by(Group) %>%
 summarize(Cnt_total = sum(ratio))) %>%
 group_by(Group) %>%
 mutate(end_angle = 2*pi*cumsum(ratio)/Cnt_total,
 start_angle = lag(end_angle, default = 0),
 mid_angle = 0.5*(start_angle + end_angle))
 #添加位置
rlabel = 0.6 
A_pies4 <- mutate(A_pies4,
 hjust = ifelse(mid_angle>pi, 1, 0),
 vjust = ifelse(mid_angle<pi/2 | mid_angle>3*pi/2, 0, 1))

rlabel = 1.05
#作图很前面一样,环形做法亦是如此
ggplot(A_pies4) +
 geom_arc_bar(aes(x0 = 0, y0 = 0, r0 = 0, r = 1,
 start = start_angle, end = end_angle, fill = disease))+
 geom_text_repel(aes(x = rlabel*sin(mid_angle), 
                     y = rlabel*cos(mid_angle), 
                     label = paste0 (round(ratio), "%"),
 hjust = hjust, vjust = vjust),nudge_x = .1,
  = 0.5,
  = FALSE) +
 coord_fixed() +
  scale_fill_manual(values = c('#E5D2DD', '#53A85F', '#F1BB72', '#F3B1A0', 
                               '#D6E7A3', '#57C3F3', '#476D87',
                               '#E59CC4', '#AB3282', '#23452F', '#BD956A'))+
 scale_x_continuous(limits = c(-1.2, 1.2), name = "", breaks = NULL, labels = NULL) +
 scale_y_continuous(limits = c(-1.2, 1.2), name = "", breaks = NULL, labels = NULL) +
 theme_void()+
 theme( = element_text(size = 14, hjust = 0.5))+
 labs(title = "Male individuals")

好了以上就是饼图的内容了,其本质是为了统计比例,结果解读比较直观,我们也是跟风做了一些变换的图形,其实最简单的饼图就可以了,各取所需。此外,还有很多其他方法制作饼图,感兴趣的自行百度了解。