R ggplot2:添加几何图形而不影响限制

R ggplot2:添加几何图形而不影响限制,r,ggplot2,R,Ggplot2,我想向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_li

我想向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
生成第二个绘图,但这有两个缺点:

  • 我必须用自己的代码计算限制(这很麻烦,而且容易出错)
  • 用我自己的代码计算极限与刻面不兼容。不可能(AFAIK)使用
    coord\u cartesian
    提供每面轴限制。但是,我需要将绘图与
    facet\u wrap(scales=“free”)
  • 如果在计算坐标极限时未考虑第二个几何图形,则可获得所需输出-在不计算自定义R代码中的极限的情况下,是否可能

    问题
    相关,但没有令人满意的答案。

    您可以先尝试计算最大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)))
    
    d1%
    变异(最大密度=圆形(最大密度(测量值)$y),2))
    ggplot(d1,aes(x=测量值))+
    几何线(aes(y=fit),颜色=“蓝色”)+
    几何密度()
    坐标笛卡尔(ylim=c(0,唯一(d1$max_dens)))
    
    您可以尝试的一件事是缩放
    fit
    并使用
    geom\u密度(aes(y=…缩放…)

    0
    1
    之间缩放
    fit

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

    这可以与
    facet\u wrap()
    结合使用:

    使用此功能,您可以组合两个绘图,从而更易于阅读:

    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")
    )
    
    这将为您提供:

    如果要比较相邻的组,可以使用
    facet\u grid()
    而不是
    facet\u wrap()
    multiplot()中使用
    cols=2

    看起来是这样的:


    很抱歉,如果我的问题不清楚的话,但这正是我想要避免的,因为这很麻烦,而且与刻面不兼容。然后请更新您的问题,并包含一个刻面示例。我尝试通过在示例中添加刻面来阐述问题,但我相信这只会模糊问题的重点(它使代码变长,并且不允许我生成清晰的“期望”输出)。我试图进一步澄清。请注意,问题的第一个版本中已经提出了与方面兼容并避免自己计算限制的要求,因此我认为您的回答与问题无关,因此值得删除。我不认为这可以在
    facet\u wrap
    的上下文中完成。解决方法d可能是事先手动裁剪数据,这样就不会有超出所需打印限制的数据,因此,
    ggplot2
    不会尝试调整轴的大小。笨拙,但在使用
    facet\u 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")
    
    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(
      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
    )