找不到对象R闪亮

时间:2020-01-29 05:55:44

标签: r shiny

我试图将在一个渲染函数中创建的数据帧访问到另一个渲染函数中。

有两个服务器输出,即lvi和Category,在lvi中我创建了Data1数据帧,而Category I已经创建了Data2数据帧。我想选择与Data1 ID匹配的Data2。

我正在按照以下步骤实现我的目标,但出现错误“找不到对象Data1”。

我的用户界面是

ui <- fluidPage(
  # App title ----
  titlePanel("Phase1"),
  fluidPage(
    column(4,
           # Input: Select a file ----
           fileInput("file1", "Import file1")
    ) 
  ),
  fluidPage(
    column(4,
           # Input: Select a file ----
           fileInput("file2", "Import File2")
    ) 

  ),
    # Main panel for displaying outputs ----
    mainPanel( 
      # Output: Data file ----
      dataTableOutput("lvi"),
      dataTableOutput("category")
    )
  )

我的服务器代码是

server <- function(input, output) {
  output$lvi <- renderDataTable({
    req(input$file1)
    Data1 <- as.data.frame(read_excel(input$file1$datapath, sheet = "Sheet1"))    
  })

  output$category <- renderDataTable({        
    req(input$file2)        
    Data2 <- as.data.frame(read_excel(input$file2$datapath, sheet = "Sheet1"))
    Data2 <- Data2[,c(2,8)]
    Data2 <- Data2[Data1$ID == "ID001",]        
  })        
}
shinyApp(ui, server)

1 个答案:

答案 0 :(得分:3)

一旦反应块执行完毕,其中的所有元素都将消失,就像一个函数一样。唯一幸存的是从该块“返回”的内容,该块通常是该块中的最后一个表达式(或在实数function中时,在return(...)中是某个表达式)。如果您将反应性(并观察)块视为“功能”,则您可能会意识到,该功能的外部唯一了解该功能的内部 是该函数是否以某种方式显式返回它。

请牢记这一点,进入一个render /反应块内部的框架的方法是不在该反应块内部进行计算:而是在其自己的数据中创建该框架-reactive阻止并在render和另一个render中使用它。

尝试一下(未试用):

server <- function(input, output) {

  Data1_rx <- eventReactive(input$file1, {
    req(input$file1, file.exists(input$file1$datapath))
    as.dataframe(read_excel(input$file1$datapath, sheet = "Sheet1"))
  })

  output$lvi <- renderDataTable({ req(Data1_rx()) })

  output$category <- renderDataTable({        
    req(input$file2, file.exists(input$file2$datapath),
        Data1_rx(), "ID" %in% names(Data1_rx()))
    Data2 <- as.data.frame(read_excel(input$file2$datapath, sheet = "Sheet1"))
    Data2 <- Data2[,c(2,8)]
    Data2 <- Data2[Data1_rx()$ID == "ID001",]        
  })        
}
shinyApp(ui, server)

但是,由于我们已经走上了“更好的设计”和“最佳实践”的道路,让我们将data2和经过data2过滤的框架同时进行……您现在可能不会单独使用它,但是通常最好将“加载/生成帧”与“渲染成漂亮的东西”分开。这样,如果您需要了解有关所加载数据的某些知识,则不必(a)将其重新加载到其他地方,效率低下;或(b)尝试破解闪亮的DataTable对象的内部结构并手动获取它。 (两者都是不好的主意。)

一个更好的解决方案可能始于:

server <- function(input, output) {

  Data1_rx <- eventReactive(input$file1, {
    req(input$file1, file.exists(input$file1$datapath))
    as.dataframe(read_excel(input$file1$datapath, sheet = "Sheet1"))
  })
  Data2_rx <- eventReactive(input$file2, {
    req(input$file2, file.exists(input$file2$datapath))
    dat <- as.dataframe(read_excel(input$file2$datapath, sheet = "Sheet1"))
    dat[,c(2,8)]
  })
  Data12_rx <- reactive({
    req(Data1_rx(), Data2_rx())
    Data2_rx()[ Data1_rx()$ID == "ID001", ]
  })

  output$lvi <- renderDataTable({ req(Data1_rx()); })
  output$category <- renderDataTable({ req(Data12_rx()); })
}
shinyApp(ui, server)

虽然此代码稍长一些,但它也将“数据加载/整理”分组在一起,并将“将数据渲染成漂亮的东西”分组在一起。而且,如果您需要查看早期数据或过滤后的数据,就可以了。

(附带说明:您可能会因此而受到的性能影响是,您现在拥有更多的数据副本。只要您不处理“大”数据,这都不是什么大问题。)