【问题标题】:Consistent width for geom_bar in the event of missing data在缺少数据的情况下,geom_bar 的宽度一致
【发布时间】:2023-03-29 05:41:01
【问题描述】:

如果在下面的时间序列示例中丢失数据,有没有办法为geom_bar() 设置恒定宽度?我试过在aes() 中设置width,但没有成功。比较代码示例下方图中 2011 年 5 月到 2011 年 6 月的条形宽度。

colours <- c("#FF0000", "#33CC33", "#CCCCCC", "#FFA500", "#000000" )
iris$Month <- rep(seq(from=as.Date("2011-01-01"), to=as.Date("2011-10-01"), by="month"), 15)

colours <- c("#FF0000", "#33CC33", "#CCCCCC", "#FFA500", "#000000" )
iris$Month <- rep(seq(from=as.Date("2011-01-01"), to=as.Date("2011-10-01"), by="month"), 15)
d<-aggregate(iris$Sepal.Length, by=list(iris$Month, iris$Species), sum)
d$quota<-seq(from=2000, to=60000, by=2000)
colnames(d) <- c("Month", "Species", "Sepal.Width", "Quota")
d$Sepal.Width<-d$Sepal.Width * 1000
g1 <- ggplot(data=d, aes(x=Month, y=Quota, color="Quota")) + geom_line(size=1)
g1 + geom_bar(data=d[c(-1:-5),], aes(x=Month, y=Sepal.Width, width=10, group=Species, fill=Species), stat="identity", position="dodge") + scale_fill_manual(values=colours)

【问题讨论】:

  • 有一个类似的问题here 但是它只处理无法处理宽度参数的statsposition='dodge' 似乎也有同样的失败。有更多ggplot 知识的人可能想参与进来,但这听起来像是一个潜在的错误。
  • 我也遇到过这个问题。很高兴知道。现在,我将使用下面发布的解决方法,用 NA 填充值。
  • 在他对github.com/tidyverse/ggplot2/issues/1776 的回复中,哈德利说:这就是躲避的工作原理。您可能想尝试分面。顺便说一句,这个问题已经在 SO:herehere 上多次解决,例如
  • 因为当我们搜索geom_bar +width +fixed时,google往往会把我们带到这里,所以我想指出这个鲜为人知的技巧:geom_bar(position = position_dodge(preserve = "single"))
  • ggplot 中有一个new dodging algorihm。当前版本(2.2.1 Nov-2017)尚未包含它。

标签: r ggplot2


【解决方案1】:

ggplot2 3.0.0 中引入的position_dodge() 和新position_dodge2() 的一些新选项可以提供帮助。

您可以在position_dodge() 中使用preserve = "single" 来确定单个元素的宽度,因此所有条形的宽度将相同。

ggplot(data = d, aes(x = Month, y = Quota, color = "Quota")) + 
     geom_line(size = 1) + 
     geom_col(data = d[c(-1:-5),], aes(y = Sepal.Width, fill = Species), 
              position = position_dodge(preserve = "single") ) + 
     scale_fill_manual(values = colours)

使用position_dodge2() 改变了事物的居中方式,使每组条形图在每个 x 轴位置居中。它内置了一些padding,所以使用padding = 0 删除。

ggplot(data = d, aes(x = Month, y = Quota, color = "Quota")) + 
     geom_line(size = 1) + 
     geom_col(data = d[c(-1:-5),], aes(y = Sepal.Width, fill = Species), 
              position = position_dodge2(preserve = "single", padding = 0) ) + 
     scale_fill_manual(values = colours)

【讨论】:

  • 我摆弄了这个选项,但我无法让它与多面图一起使用——条形图无法对齐。
【解决方案2】:

最简单的方法是补充您的数据集,以便每个组合都存在,即使它的值是 NA。举一个更简单的例子(因为你的有很多不需要的功能):

dat <- data.frame(a=rep(LETTERS[1:3],3),
                  b=rep(letters[1:3],each=3),
                  v=1:9)[-2,]

ggplot(dat, aes(x=a, y=v, colour=b)) +
  geom_bar(aes(fill=b), stat="identity", position="dodge")

这显示了您要避免的行为:在“B”组中,没有“a”组,因此条形更宽。用包含ab 的所有组合的数据框补充dat

dat.all <- rbind(dat, cbind(expand.grid(a=levels(dat$a), b=levels(dat$b)), v=NA))

ggplot(dat.all, aes(x=a, y=v, colour=b)) +
  geom_bar(aes(fill=b), stat="identity", position="dodge")  

【讨论】:

  • 我在使用 boxplot 时遇到了同样的问题,但是这种通过 NA 填充的方法并不能解决我的不等宽框问题。 NA 刚刚被删除。用 0 填充似乎可以工作,但这会产生一个包含不适当数据的非常丑陋的图。有什么建议吗?
  • @EtienneLow-Décarie 不是随便的。将其作为一个新问题提出(参考这个并展示它如何不适用于箱线图),也许其他人可以提供帮助。
  • 给未来用户的注意事项:应用此解决方案时,请特别注意数据类型(因子和数字),否则该解决方案可能看起来“损坏”(请参阅​​@EtienneLow-上面的 Décarie)。详情请查看this question
  • 老实说,我认为更改数据集以使图表看起来不错不是一个好主意。 ggplot 应该在缺少观察的情况下做得更好。
  • 我发现解决方案做得非常好,直到我没有意识到如果 GREEN 将是 NA 值而不是 RED 怎么办?在这种情况下,应用 NA 值,我在列之间只有一个空格,我的条不再“堆叠”。有什么解决办法吗?谢谢!
【解决方案3】:

我遇到了同样的问题,但正在寻找一种适用于管道的解决方案 (%&gt;%)。使用来自tidyversetidyr::spreadtidyr::gather 可以解决问题。我使用与@Brian Diggs 相同的数据,但使用大写变量名在转换为宽时不会以双变量名结束:

library(tidyverse)

dat <- data.frame(A = rep(LETTERS[1:3], 3),
                  B = rep(letters[1:3], each = 3),
                  V = 1:9)[-2, ]
dat %>% 
  spread(key = B, value = V, fill = NA) %>% # turn data to wide, using fill = NA to generate missing values
  gather(key = B, value = V, -A) %>% # go back to long, with the missings
  ggplot(aes(x = A, y = V, fill = B)) +
  geom_col(position = position_dodge())

编辑:

对于这个问题,实际上有一个更简单的解决方案,结合管道。使用tidyr::complete 在一行中给出相同的结果:

dat %>% 
  complete(A, B) %>% 
  ggplot(aes(x = A, y = V, fill = B)) +
  geom_col(position = position_dodge())

【讨论】:

  • 非常好的答案,我不知道 tidyr::complete 存在。
猜你喜欢
  • 2021-06-12
  • 2018-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-21
  • 1970-01-01
相关资源
最近更新 更多