首页 > 解决方案 > 饼图ggplot:文字方向和图形不同

问题描述

我有一个这样的数据集

data=data.frame(Var1 = c('a', 'b'), Freq=c(31, 48))

我想做一个ggplot饼图。我这样做如下

library(ggplot2)
tbl <- transform(data,
                 freq = cumsum(Freq),
                 perc = Freq/sum(Freq),
                 pos = (cumsum(Freq) - 0.5 * Freq) / sum(Freq))
ggplot(data=tbl, aes(x="", y=perc, fill = factor(Var1))) + 
  geom_bar(width = 0.8, stat="identity") + 
  coord_polar(theta="y",start = 0,  direction = 1) +
  geom_text(aes(label=paste(round(perc*100),"%",sep=""), y=pos), 
            color="grey20" ,size=15) +
  scale_fill_manual(tbl$Var1,values = c("coral2", "red")) + 
  theme_bw() + 
  theme (panel.border = element_blank(),legend.title = element_blank(),
         axis.ticks = element_blank(),axis.title.x = element_blank(), 
         axis.title.y = element_blank(), axis.text.x = element_blank(),
         axis.line=element_blank(),panel.grid.major=element_blank(),
         legend.background = element_rect(fill="transparent"), legend.position=c(0.5,0.1), 
         legend.direction="vertical", legend.text=element_text(size = 20)) 

我得到饼图 在此处输入图像描述

如您所见,文本方向和图形是不同的。我用coord_polar(theta="y",start = 0, direction = 1)direction = 1意味着顺时针方向。但实际上馅饼的方向是逆时针的。我做错了什么?

标签: rggplot2

解决方案


您的问题在于您如何计算文本位置。它与极坐标无关。

让我们看一下从 transforming 创建的数据框data

> tbl
  Var1 Freq freq      perc       pos
1    a   31   31 0.3924051 0.1962025
2    b   48   79 0.6075949 0.6962025

ggplot(data=tbl, aes(x="", y=perc, fill = factor(Var1))) + 
  geom_bar(width = 0.8, stat="identity") + 
  geom_text(aes(label=paste(round(perc*100),"%",sep=""),y=pos), color="grey20" ,size=15)

阴谋

这些显然不是文本标签的预期位置。手动计算堆叠条形图的标签位置并非完全简单,但您实际上可以让 ggplot 为您完成工作,使用position_stack()并指定您的首选vjust值。这是一个实现:

ggplot(data = tbl,
       aes(x = "", y = perc, fill = Var1)) +
  geom_col() +
  geom_text(aes(label = scales::percent(perc, accuracy = 1)),
            position = position_stack(vjust = 0.5),
            color = "grey20", size = 15) +
  coord_polar(theta = "y", direction = -1) +
  scale_fill_manual(values = c("a" = "coral2", "b" = "red")) +
  theme_void() +
  theme(legend.position = "bottom",
        legend.direction = "vertical")

上述代码的其他注意事项:

  1. 使用geom_col()代替geom_bar(stat = "identity"); 它们是等效的,前者看起来更干净;

  2. percent()从包装中使用scales来创建百分比标签;它比自己搞乱round()&更直观paste()

  3. coord_polar()具有start = 0direction = 1作为其默认参数。如果您不更改默认值,则不必指定它们;

  4. 使用命名向量以手动比例指定映射值通常更安全,以防您在多个数据集中使用相同的代码,并且并非所有值都出现在每种情况下;

  5. 如果您发现自己重复XXX = element_blank()了很多次,可能是时候切换到theme_void()并仅指定规则的例外情况。

阴谋


推荐阅读