【问题标题】:two-way density plot combined with one way density plot with selected regions in r双向密度图与 r 中选定区域的单向密度图相结合
【发布时间】:2012-07-17 18:38:33
【问题描述】:
# data 
set.seed (123)
xvar <- c(rnorm (1000, 50, 30), rnorm (1000, 40, 10), rnorm (1000, 70, 10))
yvar <-   xvar + rnorm (length (xvar), 0, 20)
myd <- data.frame (xvar, yvar)


# density plot for xvar
            upperp = 80   # upper cutoff
            lowerp = 30   # lower cutoff
            x <- myd$xvar
            plot(density(x))
            dens <- density(x)
            x11 <- min(which(dens$x <= lowerp))
            x12 <- max(which(dens$x <= lowerp))
            x21 <- min(which(dens$x > upperp))
            x22 <- max(which(dens$x > upperp))
            with(dens, polygon(x = c(x[c(x11, x11:x12, x12)]),
                y = c(0, y[x11:x12], 0), col = "green"))
             with(dens, polygon(x = c(x[c(x21, x21:x22, x22)]),
                y = c(0, y[x21:x22], 0), col = "red"))
            abline(v = c(mean(x)), lwd = 2, lty = 2, col = "red")
# density plot with yvar
    upperp = 70  # upper cutoff
    lowerp = 30   # lower cutoff
    x <- myd$yvar
    plot(density(x))
    dens <- density(x)
    x11 <- min(which(dens$x <= lowerp))
    x12 <- max(which(dens$x <= lowerp))
    x21 <- min(which(dens$x > upperp))
    x22 <- max(which(dens$x > upperp))
    with(dens, polygon(x = c(x[c(x11, x11:x12, x12)]),
        y = c(0, y[x11:x12], 0), col = "green"))
     with(dens, polygon(x = c(x[c(x21, x21:x22, x22)]),
        y = c(0, y[x21:x22], 0), col = "red"))
    abline(v = c(mean(x)), lwd = 2, lty = 2, col = "red")

我需要绘制两种密度图,我不确定是否有比以下更好的方法:

ggplot(myd,aes(x=xvar,y=yvar))+
    stat_density2d(aes(fill=..level..), geom="polygon") +
    scale_fill_gradient(low="blue", high="green") + theme_bw()

我想将所有三种类型合二为一(我不知道我是否可以在 ggplot 中创建双向图),对于解决方案是在 ggplot 中还是在基础中还是在混合中没有优先级。考虑到 R 的稳健性,我希望这是一个可行的项目。我个人更喜欢 ggplot2。

注意:此图中的下阴影不正确,xvar 和 yvar 图中的红色应始终位于下方,绿色始终位于上方,对应于 xy 密度图中的阴影区域。

编辑: 对图表的最终期望(感谢 seth 和 jon 非常接近的答案) (1) 删除空格和轴刻度标签等使其紧凑
(2) 网格对齐,以便中间的绘图刻度和网格应与侧刻度对齐,并且绘图的标签和大小看起来相同。

【问题讨论】:

  • 此处的答案可能有助于使用 ggplot stackoverflow.com/questions/8545035/… 获得密度
  • 您的问题非常鼓舞人心,我想知道您是否可以分享能够在您的帖子中绘制图形的最终代码?非常感谢。

标签: r graph ggplot2 kernel-density


【解决方案1】:

以下是使用对齐方式组合多个图的示例:

library(ggplot2)
library(grid)

set.seed (123)
xvar <- c(rnorm (100, 50, 30), rnorm (100, 40, 10), rnorm (100, 70, 10))
yvar <-   xvar + rnorm (length (xvar), 0, 20)
myd <- data.frame (xvar, yvar)

p1 <- ggplot(myd,aes(x=xvar,y=yvar))+
  stat_density2d(aes(fill=..level..), geom="polygon") +
  coord_cartesian(c(0, 150), c(0, 150)) +
  opts(legend.position = "none")

p2 <- ggplot(myd, aes(x = xvar)) + stat_density() +
  coord_cartesian(c(0, 150))
p3 <- ggplot(myd, aes(x = yvar)) + stat_density() + 
  coord_flip(c(0, 150))

gt <- ggplot_gtable(ggplot_build(p1))
gt2 <- ggplot_gtable(ggplot_build(p2))
gt3 <- ggplot_gtable(ggplot_build(p3))

gt1 <- ggplot2:::gtable_add_cols(gt, unit(0.3, "null"), pos = -1)
gt1 <- ggplot2:::gtable_add_rows(gt1, unit(0.3, "null"), pos = 0)

gt1 <- ggplot2:::gtable_add_grob(gt1, gt2$grobs[[which(gt2$layout$name == "panel")]],
                                  1, 4, 1, 4)
gt1 <- ggplot2:::gtable_add_grob(gt1, gt2$grobs[[which(gt2$layout$name == "axis-l")]],
                                 1, 3, 1, 3, clip = "off")

gt1 <- ggplot2:::gtable_add_grob(gt1, gt3$grobs[[which(gt3$layout$name == "panel")]],
                                 4, 6, 4, 6)
gt1 <- ggplot2:::gtable_add_grob(gt1, gt3$grobs[[which(gt3$layout$name == "axis-b")]],
                                 5, 6, 5, 6, clip = "off")
grid.newpage()
grid.draw(gt1)

请注意,这适用于 gglot2 0.9.1,在未来的版本中,您可能会更轻松地做到这一点。

最后

你可以这样做:

library(ggplot2)
library(grid)

set.seed (123)
xvar <- c(rnorm (100, 50, 30), rnorm (100, 40, 10), rnorm (100, 70, 10))
yvar <-   xvar + rnorm (length (xvar), 0, 20)
myd <- data.frame (xvar, yvar)

p1 <- ggplot(myd,aes(x=xvar,y=yvar))+
  stat_density2d(aes(fill=..level..), geom="polygon") +
  geom_polygon(aes(x, y), 
               data.frame(x = c(-Inf, -Inf, 30, 30), y = c(-Inf, 30, 30, -Inf)),
               alpha = 0.5, colour = NA, fill = "red") +
  geom_polygon(aes(x, y), 
               data.frame(x = c(Inf, Inf, 80, 80), y = c(Inf, 80, 80, Inf)),
               alpha = 0.5, colour = NA, fill = "green") +
  coord_cartesian(c(0, 120), c(0, 120)) +
  opts(legend.position = "none")

xd <- data.frame(density(myd$xvar)[c("x", "y")])
p2 <- ggplot(xd, aes(x, y)) + 
  geom_area(data = subset(xd, x < 30), fill = "red") +
  geom_area(data = subset(xd, x > 80), fill = "green") +
  geom_line() +
  coord_cartesian(c(0, 120))

yd <- data.frame(density(myd$yvar)[c("x", "y")])
p3 <- ggplot(yd, aes(x, y)) + 
  geom_area(data = subset(yd, x < 30), fill = "red") +
  geom_area(data = subset(yd, x > 80), fill = "green") +
  geom_line() +
  coord_flip(c(0, 120))

gt <- ggplot_gtable(ggplot_build(p1))
gt2 <- ggplot_gtable(ggplot_build(p2))
gt3 <- ggplot_gtable(ggplot_build(p3))

gt1 <- ggplot2:::gtable_add_cols(gt, unit(0.3, "null"), pos = -1)
gt1 <- ggplot2:::gtable_add_rows(gt1, unit(0.3, "null"), pos = 0)

gt1 <- ggplot2:::gtable_add_grob(gt1, gt2$grobs[[which(gt2$layout$name == "panel")]],
                                  1, 4, 1, 4)
gt1 <- ggplot2:::gtable_add_grob(gt1, gt2$grobs[[which(gt2$layout$name == "axis-l")]],
                                 1, 3, 1, 3, clip = "off")

gt1 <- ggplot2:::gtable_add_grob(gt1, gt3$grobs[[which(gt3$layout$name == "panel")]],
                                 4, 6, 4, 6)
gt1 <- ggplot2:::gtable_add_grob(gt1, gt3$grobs[[which(gt3$layout$name == "axis-b")]],
                                 5, 6, 5, 6, clip = "off")
grid.newpage()
grid.draw(gt1)

【讨论】:

    【解决方案2】:

    基于赛斯的回答(谢谢赛斯,你值得所有功劳),我改进了提问者提出的一些问题。由于 cmets 太短,无法回答所有问题,我选择将其用作答案本身。 还有几个问题,需要您的帮助

    # data
    set.seed (123)
    xvar <- c(rnorm (1000, 50, 30), rnorm (1000, 40, 10), rnorm (1000, 70, 10))
    yvar <-   xvar + rnorm (length (xvar), 0, 20)
    myd <- data.frame (xvar, yvar)
    
    require(ggplot2)
    
    # density plot for xvar
    upperp = 80   # upper cutoff
    lowerp = 30
    

    中间图

     g=ggplot(myd,aes(x=xvar,y=yvar))+
        stat_density2d(aes(fill=..level..), geom="polygon") +
        scale_fill_gradient(low="blue", high="green") + 
      scale_x_continuous(limits = c(0, 110)) + 
       scale_y_continuous(limits = c(0, 110)) + theme_bw()
    

    geom_rect 两个区域

    gbig=g+ geom_rect(data=myd, aes(  NULL,  NULL, xmin=0,  
    xmax=lowerp,ymin=0, ymax=20), fill='red', alpha=.0051,inherit.aes=F)+ 
    geom_rect(aes(NULL,  NULL,   xmin=upperp,            xmax=110, 
     ymin=upperp,            ymax=110),            fill='green',            
      alpha=.0051,
                inherit.aes=F)+   
      opts(legend.position = "none", 
      plot.margin = unit(rep(0, 4), "lines"))
    

    带阴影区域的顶部直方图

        x.dens <- density(myd$xvar)
        df.dens <- data.frame(x = x.dens$x, y = x.dens$y)
    
       dens_top <- ggplot()+geom_density(aes(myd$xvar, y = ..density..))
    + scale_x_continuous(limits = c(0, 110)) +
    geom_area(data = subset(df.dens, x <= lowerp), aes(x=x,y=y), fill = 'red') 
     +  geom_area(data = subset(df.dens, x >= upperp), aes(x=x,y=y), fill = 'green') 
     +    opts (axis.text.x=theme_blank(), axis.title.x=theme_blank(), 
      plot.margin = unit(rep(0, 4), "lines")) + xlab ("") + ylab ("") +  theme_bw()
    

    带阴影区域的右直方图

       y.dens <- density(myd$yvar)
        df.dens.y <- data.frame(x = y.dens$x, y = y.dens$y)
    
        dens_right <- ggplot()+geom_density(aes(myd$yvar, y = ..density..))
       + scale_x_continuous(limits = c(0, 110)) +
      geom_area(data = subset(df.dens.y, x <= lowerp), aes(x=x,y=y), 
      fill = 'red') 
      +  geom_area(data = subset(df.dens.y, x >= upperp), aes(x=x,y=y), 
      fill = 'green')
        +      coord_flip() + 
    
    
    opts (axis.text.x=theme_blank(), axis.title.x=theme_blank(), 
       plot.margin = unit(rep(0, 4), "lines")) + xlab ("") + ylab ("") 
       +  theme_bw()
    

    制作一个空白图表来填充角落

           empty <- ggplot()+geom_point(aes(1,1), colour="white")+ 
           scale_x_continuous(breaks = NA) + scale_y_continuous(breaks = NA) +
                  opts(axis.ticks=theme_blank(),
                       panel.background=theme_blank(),
                       axis.text.x=theme_blank(),
                       axis.text.y=theme_blank(),
                       axis.title.x=theme_blank(),
                       axis.title.y=theme_blank())
    

    然后使用grid.arrange函数:

    library(gridExtra)
     grid.arrange(dens_top, empty , gbig, dens_right, ncol=2,nrow=2,
     widths=c(2, 1), heights=c(1, 2))
    

    PS:(1)有人可以帮助完美地对齐图表吗? (2) 有人可以帮忙去除图之间的额外空间吗,我尝试调整边距 - 但是 x 和 y 密度图和中心图之间有空间。

    【讨论】:

    • 谢谢,填充区域和密度线之间似乎有差距,有什么办法可以改善吗?
    【解决方案3】:

    在我上面链接的示例中,您需要 gridExtra 包。 这是你给的g。

    g=ggplot(myd,aes(x=xvar,y=yvar))+
        stat_density2d(aes(fill=..level..), geom="polygon") +
        scale_fill_gradient(low="blue", high="green") + theme_bw()
    

    使用 geom_rect 绘制两个区域

    gbig=g+geom_rect(data=myd,
            aes(  NULL,
                NULL,
                xmin=0,
                xmax=lowerp,
                ymin=-10,
                ymax=20),
            fill='red',
            alpha=.0051,
            inherit.aes=F)+
      geom_rect(aes(    NULL,
                NULL,
                xmin=upperp,
                xmax=100,
                ymin=upperp,
                ymax=130),
                fill='green',
                alpha=.0051,
                inherit.aes=F)+
      opts(legend.position = "none") 
    

    这是一个简单的ggplot直方图;它缺少你的有色区域, 但它们很容易

      dens_top <- ggplot()+geom_density(aes(x))
      dens_right <- ggplot()+geom_density(aes(x))+coord_flip()
    

    制作一个空白图表来填充角落

      empty <- ggplot()+geom_point(aes(1,1), colour="white")+
                  opts(axis.ticks=theme_blank(), 
                       panel.background=theme_blank(), 
                       axis.text.x=theme_blank(), 
                       axis.text.y=theme_blank(),           
                       axis.title.x=theme_blank(), 
                       axis.title.y=theme_blank())
    

    然后使用grid.arrange函数:

    library(gridExtra)
    
    grid.arrange(dens_top,     empty     , 
                 gbig,         dens_right, 
                     ncol=2, 
                     nrow=2, 
                     widths=c(4, 1), 
                     heights=c(1, 4))
    

    不是很漂亮,但想法就在那里。 您还必须确保音阶匹配!

    【讨论】:

    • 感谢赛斯的回答,这确实是向前迈进了一步......我可能仍需要处理边际密度图(红色和绿色)中区域的阴影并显示平均线。还要删除密度图中的 x 轴 lebel 并使图紧凑。
    • 最重要的是所有地块中的比例 xvar 和 yvar 需要匹配...
    • 这个问题是关于设置限制的。 stackoverflow.com/questions/3606697/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 2015-12-26
    • 2021-05-25
    • 2015-04-07
    • 1970-01-01
    相关资源
    最近更新 更多