在 ggplot2 中躲避两个不同的几何体

问题描述

假设我有两个不同的数据源。一种是重复观察,一种只是模型预测的平均值+/-标准误差。

n <- 30
obs <- data.frame(
  group = rep(c("A","B"),each = n*3),level = rep(rep(c("low","med","high"),each = n),2),yval = c(
    rnorm(n,30),rnorm(n,50),90),40),55),70)
  )
) %>%
  mutate(level = factor(level,levels = c("low","high")))

model_preds <- data.frame(
  group = c("A","A","B",level = rep(c("low",mean = c(32,56,87,42,51,74),sem = runif(6,min = 2,max = 5)
)

现在我可以很容易地将这些绘制在同一张图上

p <- ggplot(obs,aes(x = level,y = yval,fill = group)) +
  geom_Boxplot() +
  geom_point(data = model_preds,y = mean),size = 2,colour = "forestgreen") +
  geom_errorbar(data = model_preds,y = mean,ymax = mean + sem,ymin = mean - sem),colour = "forestgreen",size = 1) +
  facet_wrap(~group)

enter image description here

并使用它直观地查看模型预测与观察到的结果之间的差异。

但我认为这看起来有点难看,所以理想情况下会想要从箱线图 geom 中“躲避”点和误差条 geom。

如果你能原谅我的快速绘画,像这样:

enter image description here

似乎 position_dodge() 可能是要走的路,但我还没有想出如何以这种方式组合两个不同的几何体,并且文档中没有任何示例。

可能是不可能的,但我想我会要求检查

解决方法

由于图形语法将绘图的各个方面清楚地分开,因此无法在绘图的不同层(几何图形和统计数据)之间交流信息。这也意味着位置调整不能跨层共享,因此它们可以以多层方式躲避。

您可以做的下一个最好的事情是在每一层中使用 position = position_nudge(),这样它们在各个层中似乎都被避开了。您可能还想为此调整箱线图和误差条的 width 参数。下面的例子:

library(tidyverse)

n <- 30
obs <- data.frame(
  group = rep(c("A","B"),each = n*3),level = rep(rep(c("low","med","high"),each = n),2),yval = c(
    rnorm(n,30),rnorm(n,50),90),40),55),70)
  )
) %>%
  mutate(level = factor(level,levels = c("low","high")))

model_preds <- data.frame(
  group = c("A","A","B",level = rep(c("low",mean = c(32,56,87,42,51,74),sem = runif(6,min = 2,max = 5)
)

ggplot(obs,aes(x = level,y = yval,fill = group)) +
  geom_boxplot(position = position_nudge(x = -0.3),width = 0.5) +
  geom_point(data = model_preds,y = mean),size = 2,colour = "forestgreen",position = position_nudge(x = 0.3)) +
  geom_errorbar(data = model_preds,y = mean,ymax = mean + sem,ymin = mean - sem),size = 1,width = 0.5,position = position_nudge(x = 0.3)) +
  facet_wrap(~group)

reprex package (v0.3.0) 于 2021 年 1 月 17 日创建