r-ggplot在闪亮的eventReactive()中无法正确工作



我浪费了几个小时来找出为什么当我更改输入时,我的绘图会自动更新,而它本应等待"运行"按钮,但它只是忽略了这一步骤,我最终发现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在第一次运行后不再关心run按钮,它会在你更改输入时不断更新!!然而,如果你使用简单的基本绘图函数(我在代码中添加了一个注释(,就不会有任何问题,而且效果很好!遗憾的是,我的应用程序中需要ggplot,因为基本情节很难看。我看到了使用隔离((来解决这个问题的建议,但我不知道隔离((应该放在哪里来解决我的问题。而且,当基本绘图函数没有隔离((就可以正常工作时,使用它是没有意义的,而正是ggplot造成了问题。如有任何解释,不胜感激。

如果遵循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)

我认为问题是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可能更明智,只是为了代码的一致性(其他代码都不遵循惰性原则(。

最新更新