首页 > 解决方案 > 反应值问题

问题描述

我正在尝试合并两个上传的数据帧,将其输出为表格,然后能够下载并重置输入,但只得到错误:“错误'by'必须匹配列数”。我猜我很难理解 reactiveValues,因为我不能简单地将它们称为应用程序中的数据框......

library(shiny)
library(shinyjs)
library(readxl)
library(DT)

ui <- fluidPage(
  useShinyjs(),
  fileInput('inFile1', 'Choose file'),
  fileInput('inFile2', 'Choose file'),
  actionButton('reset', 'Reset'),
  tableOutput('overlap')
)

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

  observe({
    req(input$inFile1)
    rv$data1 <- readxl::read_xls(input$inFile1$datapath)
  })
  
  observe({
    req(input$inFile2)
    rv$data2 <- readxl::read_xls(input$inFile2$datapath)
  })
  
  observeEvent(input$reset, {
    rv$data1 <- NULL
    rv$data2 <- NULL
    reset('inFile1')
    reset('inFile2')
  })
  
  dataframe<-reactive({
    if (!is.null(rv$data1) | !is.null(rv$data2))
      return(NULL)                
    df <- merge(as.data.frame(rv$data1),as.data.frame(rv$data2),by.x = 1,by.y = 1)
    colnames(df) <- c("GeneID",paste0(colnames(rv$data1)[2:ncol(rv$data1)],"_file_1"),
                      paste0(colnames(rv$data2)[2:ncol(rv$data2)],"_file_2"))
    df
  })
  
  overlap1 <- reactive({
    if(!is.null(dataframe()))
      dataframe()
  })
  
  output$overlap <- renderDataTable({
    datatable(overlap1())
  })
  
}

shinyApp(ui, server)

标签: rshiny

解决方案


乍一看,你的反应式表达对我来说很好。鉴于该错误消息,该错误是由merge(). 仔细看那里,让我印象is.null深刻的是dataframe<-reactive(. 该条件(!is.null(rv$data1) | !is.null(rv$data2))意味着您正在尝试合并两个对象,NULL因为只有这样代码才不会以return(NULL). 如果一个或两个 rv 值是“Truthy”,则代码将不会运行,所有reactive将返回的是NULL.

isTruthy()在下面使用。我认为它有两个方面的帮助:

  1. isTruthy()检查值是否包含任何“可用”的内容。这样,您不必关心如何rv初始化。它可能是NAinteger(0)其他任何没有意义的东西。isTruthy处理所有这些情况。合并现在仅在有两个具有“有意义”数据的值时发生(请注意,这并不一定意味着数据可以被强制转换为data.frame)。
  2. 它避免了 if 语句中复杂的双重否定。
  dataframe <- reactive({
    if (isTruthy(rv$data1) && isTruthy(rv$data2)) {
        df <- merge(rv$data1, rv$data2, by.x = 1,by.y = 1)
        colnames(df) <- c("GeneID", paste0(colnames(rv$data1)[2:ncol(rv$data1)], "_file_1"),
                          paste0(colnames(rv$data2)[2:ncol(rv$data2)], "_file_2"))
    } else df <- NULL

    df
  })

as.data.frame最后的调整:我在声明中删除了,merge因为合并尝试做的第一件事是将参数强制到数据框。


推荐阅读