【问题标题】:Shiny: add regression line without changing dataShiny:在不改变数据的情况下添加回归线
【发布时间】:2019-01-23 15:53:29
【问题描述】:

我正在编写一个闪亮的应用程序,用于调整绘图中的散布量。数据通过rnorm() 生成。我用ggplot2 显示情节。我想根据复选框的值显示或隐藏回归线。这一切都有效。

但是,每当我显示或隐藏回归线(不改变误差量)时,都会重新生成数据,这是我不想要的。我有一个反应函数中的数据,希望能解决问题,但它没有。

我尝试过同时使用geom_smoothgeom_abline(在代码中注释掉),但两者都会导致数据重新生成。

问题:我可以在不更改数据的情况下添加/删除回归线吗?也就是说,只有在更改滑块而不是复选框时,点的位置才应该更改。

library(shiny)
library(ggplot2)

set.seed(42)

ui <- fluidPage(

  sidebarLayout(
    sidebarPanel(
      sliderInput("stdev",
                  "Amount of error:",
                  min = 0,
                  max = 0.8,
                  value = 0.34),
      checkboxInput("showLM", "Show regression line?",
                    value = TRUE)
    ),

    mainPanel(
      plotOutput("regrPlot")
    )
  )
)

# Define server logic required to draw a histogram
server <- function(input, output) {

  output$regrPlot <- renderPlot({

    regrData <- reactive({
      pl <- rnorm(50, mean = 4.3, sd = 0.44)
      error <- rnorm(length(pl), 0, input$stdev)
      sl <- 2.41 + (0.828 * pl) + error

      tibble(pl, sl)

    })

    # For use with abline
    coefs <- lm(sl ~ pl, data = regrData())$coefficients

    p1 <- ggplot(data = regrData(), aes(x = pl, y = sl)) + 
      geom_point()

    # Try with geom_abline
    # p2 <- {if (input$showLM) p1 + 
    #     geom_abline(slope = coefs[2],
    #                 intercept = coefs[1]) 
    #   else p1}

   p2 <- {if (input$showLM)
     p1 + geom_smooth(method = "lm",
                      se = FALSE)
     else p1}

    print(p2)
  })
}

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

reprex package (v0.2.1) 于 2019-01-23 创建

【问题讨论】:

  • 您应该将reactive 移到renderPlot 之外。然后它只会在其值无效时运行。但是,您将始终需要重新渲染 ggplot。
  • 做到了。我认为它必须是显而易见的。我尝试了各种排列,除了那个。谢谢。
  • 你也可以在调用rnorm()之前使用set.seed(),这样你的“随机值”就固定了,..
  • @BigDataScientist 我将set.seed() 包含在MWE 中,但您建议set.seed()(使用时)应该在reactive() 函数内而不是其当前位置?我的理解是种子将在应用程序的初始启动时设置,因此应适用于所有后续交互。
  • 第一部分是正确的。在我的写作中有点不清楚,sry。在您的反应函数内部是一个不同的环境。您的种子不再在那里定义,...如果您将种子放在反应函数中,它应该可以工作,是的,....

标签: r ggplot2 shiny


【解决方案1】:

这里的问题是您将reactive 放入renderPlot 中,这样每次renderPlot 失效时代码都会重新运行。

相反,您应该将reactive 移到您的主要server 函数中。然后它只会在其值因input$stdev 的更改而失效时运行。

但是,当您添加回归线时,您将始终需要重新渲染 ggplot。据我所知,没有办法在不重新渲染整个情节的情况下向ggplot 添加一行。

【讨论】:

  • 有一次,我在反应函数内部绘制了大部分绘图,然后在外部添加了geom_smooth 层,沿着plot &lt;- reactive({ data and basic plot }) 的行,然后是plot() + geom_smooth(...)。情节有效,但我不知道是否每次都渲染,部分原因是我最初的问题。
【解决方案2】:

就像我在评论中写的那样,另一种方法是在反应函数中设置set.seed()

在您的反应函数内部是一个不同的环境。您的种子不再在那里定义,...如果您将种子放在反应函数中,它应该可以工作。 可以在此处找到有关范围界定的高级详细信息:https://shiny.rstudio.com/articles/scoping.html

一个更好理解的例子:

library(shiny)
set.seed(1)
print("set seed outside server function:")
print(rnorm(1))
ui <- fluidPage(

)

server <- function(input, output, session) {
  observe({
    print("new environment seed not valid")
    print(rnorm(1))
  })

  observe({
    print("new environment but set seed here as well")
    set.seed(1)
    print(rnorm(1))
  })
}

shinyApp(ui, server)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-01
    • 2022-07-12
    • 1970-01-01
    • 2016-08-13
    • 2014-08-01
    • 1970-01-01
    相关资源
    最近更新 更多