【问题标题】:Unable to get a reactiveValues df to update based on user input in Shiny无法根据 Shiny 中的用户输入来更新 reactiveValues df
【发布时间】:2019-12-14 20:04:54
【问题描述】:

我对 Shiny 很陌生,并且正在生成一个应用程序,该应用程序具有基于用户输入的基础数据修改的 VAR 模型。当我的全局环境中没有预加载任何数据时,Shiny 在启动时崩溃(我尝试在本地和外部托管数据,但仍然得到相同的结果)。

我相信这与我指定反应式数据框的方式有关,因为我可以在简单的 R 脚本中运行代码,即嵌套在 observeEvent(input$go,{ 中的所有内容。启动时,我收到以下错误:

警告:ts 中的错误:“ts”对象必须有一个或多个观察结果

如果我在 R 中的全局环境中有数据,只要我点击操作按钮,它就会用本地生成的图/数据填充,考虑到它嵌套在 observeEvent 下,这是有道理的。它不会根据用户输入(尤其是预测)进行更新。

如果我的全局环境中没有数据并且我正在链接到我的硬盘驱动器或 url,那么只要我点击操作按钮,屏幕就会变成灰色并且根本不会更新。

我正在尝试通过将四个用户输入标量应用于combined_df 中的四个变量来修改combined_df,这是一个190x7 的数据帧。然后我尝试使用先前估计的线性回归来估算 tempcombined_df 中的变量之一)的过去值。先前估计的关系的系数存储在coef 中。输出同样应该是一个 190x7 的数据帧,然后我用它来构建时间序列并重新估计 VAR 模型。

我认为我的问题与为数据框的子集指定函数有关,但我不确定如何继续。

我在下面包含了我的服务器代码:

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

    rv = reactiveValues(df_data = NULL) 

    observeEvent(input$go,{

        isolate({rv$df_data <- combine_df})

        rv$df_data$co2 <- combine_df$co2 * as.numeric(input$slider1)/100
        rv$df_data$sf6 <- combine_df$sf6 * as.numeric(input$slider2)/100
        rv$df_data$n2o <- combine_df$n2o * as.numeric(input$slider3)/100
        rv$df_data$ch4 <- combine_df$ch4 * as.numeric(input$slider4)/100
        rv$df_data$temp <- as.numeric(as.matrix(combine_df[3:6]) %*% as.matrix(coef$'fit$coefficients'[2:5]) - 97.05746141)})

        timeseries <- reactive({
            tsco2 <-ts(rv$df_data[, c('co2')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
            tssf6 <-ts(rv$df_data[, c('sf6')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
            tsn2o <-ts(rv$df_data[, c('n2o')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
            tsch4 <-ts(rv$df_data[, c('ch4')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
            trend <-ts(rv$df_data[, c('temp')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
            multiplets <- ts_c(trend, tsch4, tsco2, tsn2o, tssf6)
            #multiplets <- window(multiplets, start=c(1997, 7), end=c(2012,1))
        })

        VARmodel <-  reactive ({VAR(timeseries(), p=3, type = "both")})

        fcast_for_plot <- reactive ({forecast(VARmodel(), h=50)})

        extractresults <- reactive({
            #fcastv1 <- forecast(VARmodel(), h=100)
            results <- fcast_for_plot()$model$varresult
            fcast_trend <- forecast(results$trend$model$y)
            fcasttrend <- as.data.frame(fcast_trend$mean)
        })

        repeatableplot <- reactive ({plot(fcast_for_plot(), xlab="Year")})


        output$varplot <- renderPlot({repeatableplot()})


        output$predtable <- renderTable({
            head(extractresults())})    
    }  

编辑:用户界面代码如下。

ui <- fluidPage(
    pageWithSidebar(

        headerPanel("Greenhouse gas concentration and impact on Canadian Ground Temperature"),

        sidebarPanel(
            # Slider input for co2 change
            sliderInput("slider1", "Carbon dioxide (CO2) concentration percent change:",
                        min = 10, max = 200, value = 100),

            # Slider input for sf6 change
            sliderInput("slider2", "Sulfur hexafluoride (SF6) concentration percent change:",
                        min = 10, max = 200, value = 100),


            # Slider input for N2O change
            sliderInput("slider3", "Nitrous oxide (N2O) concentration percent change:",
                        min = 10, max = 200, value = 100),


            # Slider input for ch4 change
            sliderInput("slider4", "Methane (CH4) concentration percent change:",
                        min = 10, max = 200, value = 100),

            actionButton("go","Predict")
        ),

        mainPanel(
            plotOutput("varplot"),
            plotOutput("tempplot"),
            tableOutput("predtable")
        )
    )
)

【问题讨论】:

  • 您好,您能否也添加代码中的ui 部分?
  • @bretauv,感谢您的来信。我在帖子中添加了ui

标签: r shiny


【解决方案1】:

我发现了这个问题。解决方案是:

1) 为时间序列指定全局函数

#specifying the function that will turn our data into a time series once it's adjusted, to be applied to rv$df_data (a)
timeseries <- function(x) {
    tsco2 <-ts(x[, c('co2')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
    tssf6 <-ts(x[, c('sf6')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
    tsn2o <-ts(x[, c('n2o')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
    tsch4 <-ts(x[, c('ch4')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
    temptrend <-ts(x[, c('temp')], start=c(1997, 7),end=c(2012, 1),frequency = 12)
    assign("temptrend",temptrend,envir=.GlobalEnv)  
    multiplets <- ts_c(temptrend, tsch4, tsco2, tsn2o, tssf6)
    multiplets <- window(multiplets, start=c(1997, 7), end=c(2012,1))
    assign("multiplets",multiplets,envir=.GlobalEnv)  
    VARobject <- VAR(multiplets, p=3, type = "both")
    assign("VARobject",VARobject,envir=.GlobalEnv)  
    fcast_for_plot <- forecast::forecast(VARobject, h=50)
    assign("fcast_for_plot",fcast_for_plot,envir=.GlobalEnv)
    return(fcast_for_plot)
}


timeseries2 <- function(x) {
    tsnewtemp <- ts(x[, c('temp')], start=c(1997,7), end=c(2012,1),frequency=12)
    newtempforecast <- predict(tsnewtemp)
    assign("newtempforecast",newtempforecast,envir=.GlobalEnv)  # put it in the global env
    return(newtempforecast)
}

2) 为反应值创建一个空数据集 3)用数据框填充反应值 4)根据用户输入创建反应变量 5)一旦用户点击提交,重新计算反应变量的列

请参阅下面的最终服务器代码,其中包含解决方案步骤 2) - 5)。

还有一个有趣的事实:我认为 vars 包不接受新数据集。如果我在我们的 varest 对象 VARobject 上运行 predict 或 predict ,它会返回用于预测的空向量。

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

    #specifying a reactive dataset that is currently empty, but will be populated by our dataframe
    rv = reactiveValues(df_data = NULL)
    rv$df_data = combine_df

    #Creating reactive variables based on user inputs, as percentages
    inp1 <- reactive ({(as.numeric(input$slider1))/100})
    inp2 <- reactive ({(as.numeric(input$slider2))/100})
    inp3 <- reactive ({(as.numeric(input$slider3))/100})
    inp4 <- reactive ({(as.numeric(input$slider4))/100})

    #Upon hitting predict, we recalculate the columns of our reactive data 
    observeEvent(input$go, {
        isolate({
            rv$df_data[,3] <- (combine_df[,3] * inp1())
            rv$df_data[,6] <- (combine_df[,6] * inp2())
            rv$df_data[,4] <- (combine_df[,4] * inp3())
            rv$df_data[,5] <- (combine_df[,5] * inp4())
            rv$df_data[,2] <- (as.numeric(as.matrix(rv$df_data[3:6]) %*% as.matrix(coef$'fit.coefficients'[2:5]) - 97.05746141))
            assign("rv$df_data",rv$df_data,envir=.GlobalEnv)

        })
    })    


        a <- reactive ({timeseries(rv$df_data)})
        b <- reactive ({timeseries2(rv$df_data)})

        repeatableplot <- reactive ({plot(a(), main="Initial forecast and updated values", xlab="Year")})
        repeatableplot2 <- reactive ({plot(b(), main="Estimates of Temperature Updated Trend", xlab="Year")})
        repeatabletable <- reactive ({b()}) 

        output$varplot <- renderPlot({repeatableplot()})
        output$tempplot <- renderPlot({repeatableplot2()})
        output$predtable <- renderTable({repeatabletable()})  

    }  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 2017-04-10
    • 2019-05-05
    • 2019-08-03
    • 2017-06-27
    • 2015-08-16
    • 1970-01-01
    相关资源
    最近更新 更多