在x轴上对齐多个绘图,使其不会合并绘图

时间:2018-02-19 17:55:11

标签: r plot ggplot2 shiny vertical-alignment

我有一个闪亮的应用程序,有多个具有相同x轴的绘图,绘图需要垂直对齐而不合并,即:绘图必须是彼此独立的闪亮对象。见下面可重复的例子:

library(ggplot2)
library(shiny)

# example data
df1 <- mtcars

# my custom theme, tried many variants, seems impossible?
myTheme <- function(){
  theme(legend.position = "none",
        plot.background = element_rect(fill = "lightblue"),
        axis.text.y = element_text(margin = margin(t = 0, r = 0, b = 0, l = 2, unit = "cm")),
        axis.title.y = element_text(margin = margin(t = 0, r = 0, b = 0, l = 1, unit = "cm")),
        plot.margin = unit(c(0, 0, 0, 1), "cm")
  )}


# The App with 2 plots
runApp(
  shinyApp(
    ui = bootstrapPage(
      plotOutput('plot1', width = 800, height = 200),
      plotOutput('plot2', width = 800, height = 100)
    ),
    server = function(input, output) {
      output$plot1 <- renderPlot({
        ggplot(df1, aes(mpg, gear)) +
          geom_point() +
          coord_cartesian(xlim = c(15, 25)) +
          myTheme()
      })
      output$plot2 <- renderPlot({ 
        ggplot(df1[ df1$gear %in% c(3, 5), ], aes(mpg, gear)) +
          scale_y_continuous(name = "longName", breaks = c(3, 5), labels = c("myLongThreeeee", "My Longggg FIVE")) +
          geom_area() +
          coord_cartesian(xlim = c(15, 25)) +
          myTheme()
      })

    }
  ))

enter image description here

我试图在边距上设置我自己的myTheme()不同的设置,等等似乎不可能?

如果不可能,不是非常漂亮的解决方案suggested here,我将使用单宽度字体填充Y-tick标签,如:

scale_y_continuous(labels = function(label) sprintf('%15.2f', label)) +

其他替代方案?

注意:我知道很多包(网格,牛仔图,蛋,拼凑等)将图表合并到一个ggplot对象并对齐x轴,然后打印。在我的情况下,他们需要分开,因为用户可以更改一些ui设置,只有受影响的图表才能刷新。

TL; DR :是否可以设置“轴标题”和“轴刻度标签”空间的固定大小,以厘米为单位,例如:1厘米,4厘米?

关于情节的相关帖子:Shiny - align plots axis

2 个答案:

答案 0 :(得分:2)

大量借用@ Lyngbakr的答案。

我们可以手动将宽度设置为固定大小。这将始终对齐绘图,但不考虑轴标签的长度。我不知道如何在不使绘图相互依赖的情况下考虑两组标签。这样,您就可以删除主题中的边距内容。

library(ggplot2)
library(shiny)

# example data
df1 <- mtcars

# my custom theme, tried many variants, seems impossible?
myTheme <- function(){
  theme(legend.position = "none",
        plot.background = element_rect(fill = "lightblue")
  )}


# The App with 2 plots
runApp(
  shinyApp(
    ui = bootstrapPage(
      plotOutput('plot1', width = 800, height = 200),
      plotOutput('plot2', width = 800, height = 100)
    ),
    server = function(input, output) {
      g1 <- ggplot(df1, aes(mpg, gear)) +
        geom_point() +
        coord_cartesian(xlim = c(15, 25)) +
        myTheme()

      t1 <- ggplot_gtable(ggplot_build(g1))

      g2 <- ggplot(df1[ df1$gear %in% c(3, 5), ], aes(mpg, gear)) +
        scale_y_continuous(name = "longName", breaks = c(3, 5), labels = c("myLongThreeeee", "My Longggg FIVE")) +
        geom_area() +
        coord_cartesian(xlim = c(15, 25)) +
        myTheme()

      t2 <- ggplot_gtable(ggplot_build(g2))

      fixed_width <- unit(4, 'cm')
      t1$widths[3] <- fixed_width
      t2$widths[3] <- fixed_width

      output$plot1 <- renderPlot(plot(t1))
      output$plot2 <- renderPlot(plot(t2))
    }
  ))

enter image description here

答案 1 :(得分:1)

有点笨拙,但这似乎有效。

library(ggplot2)
library(shiny)

# example data
df1 <- mtcars

# my custom theme, tried many variants, seems impossible?
myTheme <- function(){
  theme(legend.position = "none",
        plot.background = element_rect(fill = "lightblue"),
        axis.text.y = element_text(margin = margin(t = 0, r = 0, b = 0, l = 2, unit = "cm")),
        axis.title.y = element_text(margin = margin(t = 0, r = 0, b = 0, l = 1, unit = "cm")),
        plot.margin = unit(c(0, 0, 0, 4), "cm")
  )}


# The App with 2 plots
  shinyApp(
    ui = bootstrapPage(
      plotOutput('plot1', width = 800, height = 200),
      plotOutput('plot2', width = 800, height = 100)
    ),
    server = function(input, output) {
      g1 <- ggplot(df1, aes(mpg, gear)) +
        geom_point() +
        coord_cartesian(xlim = c(15, 25)) +
        myTheme()

      t1 <- ggplot_gtable(ggplot_build(g1))

      g2 <- ggplot(df1[ df1$gear %in% c(3, 5), ], aes(mpg, gear)) +
        scale_y_continuous(name = "longName", breaks = c(3, 5), labels = c("myLongThreeeee", "My Longggg FIVE")) +
        geom_area() +
        coord_cartesian(xlim = c(15, 25)) +
        myTheme()

      t2 <- ggplot_gtable(ggplot_build(g2))

      maxwidth <- unit.pmax(t1$widths[2:3], t2$widths[2:3])

      t1$widths[2:3] <- maxwidth
      t2$widths[2:3] <- maxwidth

      output$plot1 <- renderPlot({
        plot(t1)
      })
      output$plot2 <- renderPlot({ 
        plot(t2)
      })

    }
  )