ggplots 在模块化闪亮应用程序中的对齐方式

alignment of ggplots in a modularized shiny app

我有一个模块化的闪亮应用程序,可以实时显示 4 个变量。监控模块以一个大数据帧作为输入,显示分配的信号。 4个模块堆叠在一起 ui:

    tabBox(id = "monitoring_tabBox",
           height = monitor_height_px,
           width = "500px",
           tabPanel(id = "layout1",
             title = "Layout 1",
             monitorModuleUI("sbto2"),
             monitorModuleUI("icp"),
             monitorModuleUI("map"),
             monitorModuleUI("ptio2")
           )
    ),

问题如下:各模块之间的绘图未完全对齐。主要是因为 y ticks 值有不同的范围(看 icp 和 ptio2 是如何对齐的,因为两个信号都是两位数字,没有小数)

我见过几种对齐 ggplot 的技术,但您需要将 4 个绘图作为输入,然后将它们全部合并到一个绘图/渲染中。我想避免这一步以保持应用程序的模块化结构。

有什么方法可以对齐这些图而不必将它们合并在一起? (即通过限制 y 刻度的长度)

提前致谢!

截图:

screenshot showing the 4 modules and the misalignment issue

可重现的例子:

library(shiny)
library(dplyr)
library(ggplot2)
library(tidyr)


# Sample Data

df <- data.frame(timestamp = seq(as.POSIXct("2020-06-01 10:00:00"), as.POSIXct("2020-06-01 12:00:00"), "1 min"),
                 sbto2 = round(10000*rnorm(121, 0, 2), 1),
                 map = round(100*rnorm(121, 0, 2), 1),
                 icp = round(10*rnorm(121, 0, 1.5), 1),
                 ptio2 = round(1000*rnorm(121, 0, 1.2), 1))

# monitorModule

monitorModuleUI <- function(id){

  ns <- NS(id)

  fluidRow(
    column(8,
           plotOutput(ns("monitoring_plot"),
                      height = "150px")     
    ),
    column(2,
           uiOutput(ns("monitoring_text"))
    )
  )




}

monitorModule <- function(input, output, server, variable_name, df){

  output$monitoring_plot <- renderPlot({
    p()
  })

  p <- reactive({
    df %>%
      gather("var", "value",seq(2,5)) %>%
      filter(var == variable_name) %>%
      ggplot(aes(x = timestamp, y = value)) + geom_line() -> p

    return(p)
  })

  output$monitoring_text <- renderUI({
    value <- p()$data$value[nrow(p()$data)]
    h1(strong(paste(value)), style = "font-size:90;")
  })

}

# APP

ui <- shinyServer(fluidPage(

  monitorModuleUI("sbto2"),
  monitorModuleUI("icp"),
  monitorModuleUI("ptio2"),
  monitorModuleUI("map")

))


server <- shinyServer(function(input, output, session){

  callModule(monitorModule, "sbto2", "sbto2", df)
  callModule(monitorModule, "icp", "icp", df)
  callModule(monitorModule, "ptio2", "ptio2", df)
  callModule(monitorModule, "map", "map", df)

})

shinyApp(ui=ui,server=server)

一种替代方法是 return 每个模块的反应图,然后用包 {patchwork}.

组织它们

这是一个例子:

library(shiny)
library(dplyr)
library(ggplot2)
library(tidyr)
library(patchwork)

# Sample Data

df <- data.frame(timestamp = seq(as.POSIXct("2020-06-01 10:00:00"), as.POSIXct("2020-06-01 12:00:00"), "1 min"),
                 sbto2 = round(10000*rnorm(121, 0, 2), 1),
                 map = round(100*rnorm(121, 0, 2), 1),

                              icp = round(10*rnorm(121, 0, 1.5), 1),
                 ptio2 = round(1000*rnorm(121, 0, 1.2), 1))

# monitorModule

monitorModuleUI <- function(id){
  # ns <- NS(id)
  # plotOutput(ns("monitoring_plot"),
  #            height = "150px")
}

monitorModule <- function(input, output, server, variable_name, df){

  test <- reactive({
    df %>%
      gather("var", "value",seq(2,5)) %>%
      filter(var == variable_name) %>%
      ggplot(aes(x = timestamp, y = value)) + geom_line() -> p

    return(p)
  })

}

# APP

ui <- fluidPage(

  monitorModuleUI("sbto2"),
  monitorModuleUI("icp"),
  monitorModuleUI("ptio2"),
  monitorModuleUI("map"),

  plotOutput("all_plots")

)


server <- function(input, output, session){

  plot_1 <- callModule(monitorModule, "sbto2", "sbto2", df)
  plot_2 <- callModule(monitorModule, "icp", "icp", df)
  plot_3 <- callModule(monitorModule, "ptio2", "ptio2", df)
  plot_4 <- callModule(monitorModule, "map", "map", df)

  output$all_plots <- renderPlot({
    plot_1() / plot_2() / plot_3() / plot_4()
 })

}

shinyApp(ui=ui,server=server)