在闪亮的应用程序中的反应上下文中使用数值

时间:2020-02-29 15:25:45

标签: r loops shiny reactive-programming

我刚刚开始研究闪亮的应用程序,因此很可能这是一个非常基本的问题,但是在论坛上搜索后,我仍然无法正常工作。

作为我的第一个应用程序的一部分,我模拟了一个恰好100000个案例的种群,我希望使用for循环从中抽取n个随机样本。 因此,一般代码如下:

samples<-list(NULL)
for(i in 1:100){samples[[i]]<-dplyr::sample_n(population, size=200, replace=FALSE)}

现在,我想包括一个滑块,该滑块将替换for循环中的100,以便用户可以决定要绘制多少个样本。 但是,在用户界面中定义滑块然后在服务器端尝试以下操作

samples<-list(NULL)
for(i in 1:input$n_samples){samples[[i]]<-dplyr::sample_n(population, size=200, replace=FALSE)} 

我收到以下错误:

.getReactiveEnvironment()$ currentContext()中的错误:操作不正确 允许没有活动的反应上下文。 (您尝试做某事 只能从反应表达式或观察者内部完成。)

接下来我尝试了

samples <- reactive({   
samples<-list(NULL)
for(i in 1:input$n_samples){samples[[i]]<-dplyr::sample_n(population, size=200, replace=FALSE)}     
})  

以及带有reactVal()和reactValues()的版本以及各种变体,但没有成功。

因此,基本上,我想要的是用户通过滑块选择的值确定我的for循环中的重复次数。

我也看到了这个线程,但是不知道这是否是一个类似的问题: For loop inside reactive function in Shiny 希望有人能对此有所启发。

1 个答案:

答案 0 :(得分:0)

他们说,在R中,增加列表不是一个好主意。您应该预先分配列表并迭代地填充空格。下面的应用程序将执行此操作。

基于填充量(mtcars),更改滑块会触发绘制与滑块值一样多的10个值的样本。可以通过调用samples()来读取结果。每次滑块变化时,samples()都会更新(注意:不是samples(它只是一个函数,而是samples())(它是函数调用的结果,绘制的样本):

library(shiny)
library(dplyr)

population <- mtcars


ui <- fluidPage(h4("You have a population of", nrow(population), "values. Choose the number of random sample sets"),
                h5("(each sample contains 10 values):"),
                sliderInput("n", "Number of samples", min=1, max = 1000, value = 5),
                textOutput("summary"))


server <- function(input, output) {

    # a normal function that draws a sample of 10 values
    draw_single_sample <- function(x) sample_n(population, size = 10)

    # A reactive function that takes slider value and produce as many samples as the slider requests
    samples <- reactive(lapply(1:input$n, draw_single_sample))

    # Dependend on samples (thus input$n), print the result of the random draw
    output$summary <- renderText({
        samples_concrete <- samples()
        paste("Finished calculation. You have", length(samples_concrete),
              "random samples of 10 values each Mean values of the first columns:",
              toString(sapply(samples_concrete, function(x) mean(x[[1]]))))
    })
}

shinyApp(ui = ui, server = server)