【问题标题】:Manipulating reactive objects in Shiny - Error in <-: invalid (NULL) left side of assignment在 Shiny 中操作反应性对象 - <- 中的错误:赋值左侧无效(NULL)
【发布时间】:2017-11-08 17:44:18
【问题描述】:

当我尝试在 Shiny 中获取反应性对象并进一步操作它时,我一遍又一遍地遇到错误“

 testdf <- data.frame(row1 = c(1,3,6), row2 = c(7, 5, 1))

 ui <- fluidPage(

   titlePanel("Education in Tanzania"),

   sidebarLayout(
     sidebarPanel(


       #Select aggregation level of data
       selectInput("AggregationSelect", 
                   label = "Aggregation",
                   choices = list("School" = 1, 
                                  "District" = 2, 
                                  "Region" = 3),
                   selected = 1)
     ),

     mainPanel(
       DT::dataTableOutput("OutputTable")
     )
   )
 )

 server <- function(input, output) {

     Output1 <- reactive({
         testdf
     })

   observe({
     if(2 %in% input$AggregationSelect) {
       observe({Output1()$name[3] <- "b"})
     } else  if(3 %in% input$AggregationSelect) {
       observe({Output1()$name[2] <- "c"})
     } else  if(1 %in% input$AggregationSelect) {
       observe({Output1()$name[1] <- "a"})
     }
   })

   output$OutputTable <- {DT::renderDataTable({
     DT::datatable(Output1(),
                   options = list(pagelength = 25,
                                  searching = TRUE,
                                  paging = TRUE,
                                  lengthChange = FALSE),
                   rownames = FALSE)
     })
   }
 }  

 shinyApp(ui = ui, server = server)

在我的实际代码中我需要做的是通过 UI 组装一个数据框(我可以这样做,因此在这里只是替换了一个随机 df),然后添加一些信息(这里用添加的“名称”表示" 列)基于在 UI 中选择的内容。似乎将列添加到 df 应该不那么难,但是在反应对象上下文中,我尝试过的任何事情都没有奏效。欢迎使用其他修改反应性对象的方法,只要它们可以应用于更复杂的多步骤场景 - 我无法将所需的所有内容捆绑到反应性对象的初始分配中。

【问题讨论】:

  • 你在testdf 中没有名为name 的变量

标签: r shiny reactive


【解决方案1】:
  1. 无法从外部修改反应式表达式。您只能修改反应值。

  2. 通常您永远不需要使用observe。如果您不需要副作用,请使用响应式表达式,在需要时使用带有 observeEvent 的响应式值。

  3. 必须在继续之前阅读反应式教程。在做任何复杂的事情之前,需要理解一些概念,尤其是“强制更新习惯”。您需要让 Shiny 正确进行更新并正确设置逻辑。

我建议你阅读 RStudio 网站上所有关于响应式的教程、文章,然后观看the reactive tutorial video in Shiny conference

【讨论】:

  • 此错误并非特定于 Shiny 或响应式。你可以用纯 R 格式得到它。例如,bogus() &lt;- 4 给出 Error in bogus() &lt;- 4 : invalid (NULL) left side of assignment
  • 这与问题完全不同,因为错误消息是通用的。您的示例正在尝试修改无效的 synyax 函数调用。
【解决方案2】:

我不是 100% 你在做什么,但我认为最好使用eventReactive 来听你的selectInput。请注意,我将变量 names 添加到数据框:

library(shiny)
testdf <- data.frame(names = c(1,3,6), row2 = c(7, 5, 1))

ui <- fluidPage(
  titlePanel("Education in Tanzania"),
  sidebarLayout(
    sidebarPanel(
      #Select aggregation level of data
      selectInput("AggregationSelect", label = "Aggregation",
                  choices = list("School" = 1, "District" = 2, "Region" = 3),selected = 1)
    ),
    mainPanel(
      DT::dataTableOutput("OutputTable")
    )
  )
)

server <- function(input, output) {

  Output1 <- eventReactive(input$AggregationSelect,{
    if(input$AggregationSelect %in% "2"){
      testdf$name[3] <- "b"
      return(testdf)
    }
    else if(input$AggregationSelect %in% "3"){
      testdf$name[2] <- "c"
      return(testdf)
    }
    else if(input$AggregationSelect %in% "1"){
      testdf$name[1] <- "a"
      return(testdf)
    }
    else{
      return(testdf)
    }
  })

  output$OutputTable <- {DT::renderDataTable({
    print(Output1())
    DT::datatable(Output1(),options = list(pagelength = 25,searching = TRUE,paging = TRUE,lengthChange = FALSE),rownames = FALSE)
  })
  }
}  

shinyApp(ui = ui, server = server)

【讨论】:

  • testdf 只是一个例子。我所拥有的已经是一个反应性对象(一个数据框),然后我需要对其进行操作,这就是我使用 Output1 的原因。感谢这个快捷方式,但它不适用于我的实际代码,因为我没有数据框可以开始
【解决方案3】:

根据我对您的问题的理解,我已将您的代码调整如下:

testdf <- data.frame(name = c(1,2,3), freq = c(100, 200, 300))

ui <- fluidPage(

titlePanel("Education in Tanzania"),

sidebarLayout(
sidebarPanel(


  #Select aggregation level of data
  selectInput("AggregationSelect", 
              label = "Aggregation",
              choices = list("School" = 1, 
                             "District" = 2, 
                             "Region" = 3))
),

mainPanel(
  DT::dataTableOutput("OutputTable")
 )
))

server <- function(input, output) {

Output1 <- reactive({
input$AggregationSelect
selection <- input$AggregationSelect

if(2 %in% selection){
  testdf$name[3] <- "b"
} 
else if(3 %in% selection){
  testdf$name[2] <- "c"
} 
else if(1 %in% selection){
  testdf$name[1] <- "a"
}
testdf
})

output$OutputTable <- {DT::renderDataTable({
DT::datatable(Output1(),
              options = list(pagelength = 25,
                             searching = TRUE,
                             paging = TRUE,
                             lengthChange = FALSE),
              rownames = FALSE)
})
}}  

shinyApp(ui = ui, server = server)

【讨论】:

  • testdf 只是一个例子。我所拥有的已经是一个反应性对象(一个数据框),然后我需要对其进行操作,这就是我使用 Output1 的原因。欣赏快捷方式,但它不适用于我的实际代码...
  • @Clare,你需要操作更大的响应式数据框吗?
  • 是的,更大的数据框需要在组装后进行操作(根据整个 df 获取一些统计数据,根据结果分配因子水平)。
猜你喜欢
  • 2016-06-16
  • 2019-09-18
  • 1970-01-01
  • 2017-04-26
  • 1970-01-01
  • 1970-01-01
  • 2020-12-06
  • 2019-01-24
  • 1970-01-01
相关资源
最近更新 更多