【问题标题】:ggplot2: Adding a geom without affecting limitsggplot2:添加几何而不影响限制
【发布时间】:2018-04-05 01:51:52
【问题描述】:

我想在 ggplot 密度图中添加额外的几何图形,但不会更改数据的显示限制,也无需通过自定义代码计算所需的限制。举个例子:

set.seed(12345)
N = 1000
d = data.frame(measured = ifelse(rbernoulli(N, 0.5), rpois(N, 100), rpois(N,1)))
d$fit = dgeom(d$measured, 0.6)
ggplot(d, aes(x = measured)) + geom_density() + geom_line(aes(y = fit), color = "blue")

ggplot(d, aes(x = measured)) + geom_density() + geom_line(aes(y = fit), color = "blue") + coord_cartesian(ylim = c(0,0.025))

在第一个图中,拟合曲线(与“测量”数据的拟合非常差)掩盖了测量数据的形状: 我想裁剪绘图以包含第一个几何图形的所有数据,但裁剪拟合曲线,如第二个绘图所示:

虽然我可以使用coord_cartesian 生成第二个图,但这有两个缺点:

  1. 我必须通过自己的代码计算限制(这很麻烦且容易出错)
  2. 用我自己的代码计算限制与分面不兼容。不可能 (AFAIK) 使用 coord_cartesian 提供每个方面的轴限制。但是,我需要将情节与facet_wrap(scales = "free") 结合起来

如果在计算坐标限制时不考虑第二个几何图形,则可以实现所需的输出 - 在自定义 R 代码中不计算限制是否可能?

问题 R: How do I use coord_cartesian on facet_grid with free-ranging axis 相关,但没有满意的答案。

【问题讨论】:

  • 我不认为可以在facet_wrap 的上下文中完成。一种解决方法可能是事先手动裁剪数据,这样就没有超出所需绘图限制的数据,因此,ggplot2 不会尝试调整轴的大小。笨拙,但在使用 facet_wrap 时我想不出替代方案。

标签: r ggplot2


【解决方案1】:

您可以尝试的一件事是扩展 fit 并使用 geom_density(aes(y = ..scaled..)

01 之间缩放fit

d$fit_scaled <- (d$fit  - min(d$fit)) / (max(d$fit) - min(d$fit))

使用fit_scaled..scaled..

ggplot(d, aes(x = measured)) + 
  geom_density(aes(y = ..scaled..)) + 
  geom_line(aes(y = fit_scaled), color = "blue")

这可以和facet_wrap()结合使用:

d$group <- rep(letters[1:2], 500) #fake group

ggplot(d, aes(x = measured)) + 
  geom_density(aes(y = ..scaled..)) + 
  geom_line(aes(y = fit_scaled), color = "blue") + 
  facet_wrap(~ group, scales = "free")

不缩放数据的选项:

你可以从http://www.cookbook-r.com/Graphs/Multiple_graphs_on_one_page_(ggplot2)/使用函数multiplot()

multiplot <- function(..., plotlist=NULL, file, cols=1, layout=NULL) {
  library(grid)
  plots <- c(list(...), plotlist)

  numPlots = length(plots)

  if (is.null(layout)) {

    layout <- matrix(seq(1, cols * ceiling(numPlots/cols)),
                    ncol = cols, nrow = ceiling(numPlots/cols))
  }

 if (numPlots==1) {
    print(plots[[1]])

  } else {

    grid.newpage()
    pushViewport(viewport(layout = grid.layout(nrow(layout), ncol(layout))))

    for (i in 1:numPlots) {

      matchidx <- as.data.frame(which(layout == i, arr.ind = TRUE))

      print(plots[[i]], vp = viewport(layout.pos.row = matchidx$row,
                                      layout.pos.col = matchidx$col))
    }
  }
}

使用此功能,您可以将两个图表组合在一起,这样更易​​于阅读:

multiplot(
  ggplot(d, aes(x = measured)) + 
    geom_density() +
    facet_wrap(~ group, scales = "free"),
  ggplot(d, aes(x = measured)) +  
    geom_line(aes(y = fit), color = "blue") + 
    facet_wrap(~ group, scales = "free")
)

这会给你:

如果您想比较相邻的组,您可以在multiplot() 中使用facet_grid() 而不是facet_wrap()cols = 2

multiplot(
  ggplot(d, aes(x = measured)) + 
    geom_density() +
    facet_grid(group ~ ., scales = "free"),
  ggplot(d, aes(x = measured)) +  
    geom_line(aes(y = fit), color = "blue") + 
    facet_grid(group ~ ., scales = "free"),
  cols = 2
)

它看起来像这样:

【讨论】:

  • 我喜欢这个技巧,但我认为它掩盖了两条曲线之间的差异 - 虽然我可以看到它们不同,但我无法判断哪些区域适合高于/低于实际密度....
【解决方案2】:

您可以先尝试计算最大 y 限制。然后情节。

d1 <- d %>% 
  mutate(max_dens=round(max(density(measured)$y), 2))

ggplot(d1, aes(x=measured)) + 
   geom_line(aes(y=fit), color = "blue") +
   geom_density() + 
   coord_cartesian(ylim = c(0, unique(d1$max_dens)))

【讨论】:

  • 对不起,如果我的问题不清楚,但这正是我想要避免的,因为它很麻烦并且与分面不兼容。
  • 那么请更新您的问题并包含一个带有方面的示例。
  • 我已经尝试通过在示例中添加分面来制定问题,但我相信它只会掩盖这一点(它使代码更长并且不会让我产生清晰的“所需”输出)。我试图进一步澄清。请注意,与方面兼容并避免自己计算限制的要求已经出现在问题的第一个版本中,因此我认为您的答案与问题无关,因此值得删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-01
  • 1970-01-01
相关资源
最近更新 更多