首页 文章

使用网格对齐ggplot2轴

提问于
浏览
6

我有一个带有奇数个刻面的 ggplot2 线图 . 我想在空白处添加一个x值边缘分布的箱线图 . 箱线图应该是水平的,并与其他刻面共享一个共同的x轴 . 由于默认的boxplot geom是垂直的,因此需要 coord_flip() . 因此,我认为不可能将boxplot数据包含在与使用虚拟因子变量进行分面的其他方面相同的df中 .

使用 grid ,我可以识别空视口并插入箱图,但我想让x轴排成一行 . 类似问题的答案(参见herehere)建议在 ggExtra 包中使用 align_plots ,但我不会在下面包含一个简单的可重现示例 . 如果我这样做,我还必须编辑空面板Grob以创建一个与其他面相匹配的新标签 . 任何建议,将不胜感激 .

library(ggplot2)
#generate df for faceted line graphs
df <- data.frame(x = rep(1:100, times=7),
        facet_var = as.factor(rep( 1:7, each=100)),
        y = runif(7*100)
      ) 
#create faceted line graphs
p <- ggplot(data = df, aes(x, y)) +
    geom_line() + facet_wrap( ~ facet_var, ncol=2)

#generate df for boxplot
xdata <- runif(1000, min = 0, max = 100)
boxdf <- data.frame(x=xdata, group=rep(1,length(xdata)))

#create boxplot removing axes and margins
q <- ggplot(data = boxdf, aes(as.factor(group),x)) + geom_boxplot() +
       coord_flip() + labs(x=NULL) +
       opts(axis.text.x = theme_blank(), axis.title.x=theme_blank(),
         axis.text.y = theme_blank(), axis.title.y=theme_blank(),
         axis.ticks = theme_segment(colour = "white"),
         panel.margin = 0, plot.margin = unit(rep(0,4), "lines")
       )

print(p)
downViewport("panel-14-5")
print(q, newpage=F)

Edit: 在kohske的有用答案之后,我尝试调整代码以适应不同的x限制和中断 . 这里的代码只包含x限制和中断(0,80)的中断 . 可能我在代码中遗漏了一些需要随着限制而改变的东西 .

library(ggplot2)
df <- data.frame(x = rep(1:80, times=7),
        facet_var = as.factor(rep( 1:7, each=80)),
        y = runif(7*80)
      ) 

# label for marginal plot
df <- rbind(df, data.frame(x = NA, y = NA, facet_var = "Boxplot wow"))

p <- ggplot(data = df, aes(x, y)) +
    geom_line() + facet_wrap( ~ facet_var, ncol=2) + 
    # set limits for adjustment
    coord_cartesian(xlim = c(0, 80)) +
    #scale_x_continuous(breaks = 1:4*20)
    opts()

xdata <- runif(1000, min = 0, max = 80)
boxdf <- data.frame(x=xdata, group=rep(1,length(xdata)))

q <- ggplot(data = boxdf, aes(as.factor(group),x)) + geom_boxplot() +

    # set breaks and limits for adjustment
    coord_flip(ylim = c(0, 80)) + labs(x=NULL) + 
    scale_y_continuous(breaks = 1:4*20) + 

    # opts for full region drawing: 
    # see https://kohske.wordpress.com/2010/12/25/drawing-on-full-region-in-ggplot2/
    opts(
    legend.position = "none",
    panel.margin = unit(0,"null"),
    plot.margin = rep(unit(0,"null"),4),
    axis.ticks = theme_blank(),
    axis.text.x = theme_blank(),
    axis.text.y = theme_blank(),
    axis.title.x = theme_blank(),
    axis.title.y = theme_blank(),
    axis.ticks.length = unit(0,"null"),
    axis.ticks.margin = unit(0,"null")
  )

print(p)

# remove unused panel
grid.remove("panel-14-5")

downViewport("panel-14-5")
print(q, newpage=F)

enter image description here

1 回答

  • 7

    这是一个有点脏的黑客:

    library(ggplot2)
    df <- data.frame(x = rep(1:100, times=7),
            facet_var = as.factor(rep( 1:7, each=100)),
            y = runif(7*100)
          ) 
    
    # label for marginal plot
    df <- rbind(df, data.frame(x = NA, y = NA, facet_var = "Boxplot wow"))
    
    p <- ggplot(data = df, aes(x, y)) +
        geom_line() + facet_wrap( ~ facet_var, ncol=2) + 
        # set limits for adjustment
        coord_cartesian(xlim = c(0, 100))
    
    xdata <- runif(1000, min = 20, max = 80)
    boxdf <- data.frame(x=xdata, group=rep(1,length(xdata)))
    
    q <- ggplot(data = boxdf, aes(as.factor(group),x)) + geom_boxplot() +
    
        # set breaks and limits for adjustment
        coord_flip(ylim = c(0, 100)) + labs(x=NULL) + 
        scale_y_continuous(breaks = 1:5*20) + 
    
        # opts for full region drawing: 
        # see https://kohske.wordpress.com/2010/12/25/drawing-on-full-region-in-ggplot2/
        opts(
        legend.position = "none",
        panel.margin = unit(0,"null"),
        plot.margin = rep(unit(0,"null"),4),
        axis.ticks = theme_blank(),
        axis.text.x = theme_blank(),
        axis.text.y = theme_blank(),
        axis.title.x = theme_blank(),
        axis.title.y = theme_blank(),
        axis.ticks.length = unit(0,"null"),
        axis.ticks.margin = unit(0,"null")
      )
    
    print(p)
    
    # remove unused panel
    grid.remove("panel-14-5")
    
    downViewport("panel-14-5")
    print(q, newpage=F)
    

    enter image description here

相关问题