ggplot 无法在 eventReactive() 中正常工作

时间:2021-03-28 08:06:29

标签: r ggplot2 shiny

我浪费了几个小时来找出为什么当我更改输入时我的绘图会自动更新,而它应该等待“运行”按钮,但它只是忽略了这一步,我最终发现 ggplot 是麻烦制造者!!!这是我的最小代码:

library(ggplot2)
library(tidyverse)

varnames <- names(cars)

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fluidRow(
        column(
          width = 12,

          # Variables Inputs:
          varSelectInput("variables", "Select Input Variables", cars, multiple = TRUE),
          selectizeInput("outvar", "Select Output Variable", choices = varnames, "speed", multiple = F),

          # Run Button
          actionButton(inputId = "run", label = "Run")
        )
      )
    ),

    # Main panel for displaying outputs ----
    mainPanel(
      plotOutput("plot")
    )
  )
)

server <- function(input, output, session) {
  
  df <- reactive({
    cars %>% dplyr::select(!!!input$variables, input$outvar)
  })


  plt <- eventReactive(input$run, {
    
    #Just creating lm formula
    current_formula <- paste0(input$outvar, " ~ ", paste0(input$variables, collapse = " + "))
    current_formula <- as.formula(current_formula)
    #Fitting lm
    fit <- lm(current_formula, data = df())
    pred <- predict(fit, newdata = df())

    #Plotting
    ggplot(df(), aes(df()[, input$outvar], pred)) +
      labs(x = "Observed", y = "Predicted") +
      geom_point() +
      theme_bw()

     #plot(df()[, input$outvar], pred)       #This one works fine!!!!
  })


  output$plot <- renderPlot({
     plt()
  })
}

# Run the application
shinyApp(ui = ui, server = server)

如果你运行它,你会注意到 ggplot 在第一次运行后不再关心运行按钮,它会随着你改变输入而不断更新!!但是,如果您使用简单的基本绘图函数(我在代码中添加了注释),就不会有任何问题,而且效果很好!可悲的是,我的应用程序中需要 ggplot,因为基本图很难看。我看到了使用isolate()来解决这个问题的建议,但我不知道应该把isolate()放在哪里来解决我的问题,当基本绘图功能没有它时使用isolate()也没有意义,并且这是造成问题的ggplot。任何解释将不胜感激。

2 个答案:

答案 0 :(得分:1)

如果您遵循 ggplot 传递列名的首选方法,即使用 .data,它似乎工作正常。

library(ggplot2)
library(shiny)

server <- function(input, output, session) {
  
  df <- reactive({
    cars %>% dplyr::select(!!!input$variables, input$outvar)
  })
  
  
  plt <- eventReactive(input$run, {
    
    #Just creating lm formula
    current_formula <- paste0(input$outvar, " ~ ", paste0(input$variables, collapse = " + "))
    current_formula <- as.formula(current_formula)
    #Fitting lm
    fit <- lm(current_formula, data = df())
    pred <- predict(fit, newdata = df())
    

    #Plotting
    ggplot(df(), aes(.data[[input$outvar]], pred)) +
      labs(x = "Observed", y = "Predicted") +
      geom_point() +
      theme_bw()
  })
  
  
  output$plot <- renderPlot({
    plt()
  })
}

# Run the application
shinyApp(ui = ui, server = server)

答案 1 :(得分:1)

我认为问题在于 ggplot 正在懒惰地处理事情。如果您对代码进行一项更改以预拉 df()input$outvar,则过度反应已修复:

  plt <- eventReactive(input$run, {
    #Just creating lm formula
    current_formula <- paste0(input$outvar, " ~ ", paste0(input$variables, collapse = " + "))
    current_formula <- as.formula(current_formula)
    #Fitting lm
    fit <- lm(current_formula, data = df())
    pred <- predict(fit, newdata = df())

    #Plotting
    dat <- df()
    outv <- input$outvar
    ggplot(dat, aes(dat[, outv], pred)) +
      labs(x = "Observed", y = "Predicted") +
      geom_point() +
      theme_bw()

     #plot(df()[, input$outvar], pred)       #This one works fine!!!!
  })

问题在于 ggplot 以某种方式在内部保留了一些反应性。

(我将分配给 datoutv 紧接在 ggplot 之前,只是为了演示。在 eventReactive 中首先分配它们可能更明智阻止并使用 dat 进行所有操作,只是为了代码的一致性(其他代码都没有按照惰性原则运行)。