【问题标题】:Modifying and combining a reactive dataframe uploaded by the user in a shiny app在闪亮的应用程序中修改和组合用户上传的反应数据框
【发布时间】:2016-12-15 12:46:06
【问题描述】:

我正在创建一个闪亮的应用程序,其中一部分是根据用户上传和修改的数据计算线性回归模型。 我正在一步一步地做所有事情,所以在这里我将只向您展示一个测试应用程序的代码,涉及主要问题。这个想法是:

  1. 用户使用闪亮的fileInput 从 .csv 文件上传数据
  2. 数据显示出来后,用户可以修改 他选择的变量
  3. 每个选定和修改的变量都与旧变量一起显示 作为一个新的反应数据表 - 我设法通过它的帮助 这个: Add values to a reactive table in shiny

现在,当指定初始数据集时,下面的代码一切正常:

test_df <- data.frame(a = seq(1000, 21000, 1000), b = seq(1:21), c = seq(100, 300, 10))

library(shiny)

runApp(list(
  ui=pageWithSidebar(headerPanel("Adding entries to table"),
                 sidebarPanel(uiOutput("select1"),
                              selectInput("select2", "Choose modification",
                                          choices = c("log", "different"), 
                                          selected = NULL, multiple = F),
                              actionButton("update", "Update Table")),
                 mainPanel(tableOutput("table1"))),

server=function(input, output, session) {

values <- reactiveValues()

### specifing the dataset ###
values$df <- data.frame(test_df)
nr <<- nrow(test_df)

### this will contain the modified values ###
values$d <- data.frame(1:nr)

### selecting a variable to modify ###
output$select1 <- renderUI({
  nc <- ncol(values$df)
  nam <- colnames(values$df)
  selectInput("var", label = "Select var:",
              choices = c(nam), multiple = F,
              selected = nam[1])
})

### calculations needed for modifactions ###
newEntry <- observeEvent(input$update, {

  if(input$select2 == "log") {
    newCol <- isolate(
      c(log(values$df[input$var]))
    )
    newCol <- as.data.frame(newCol)
    colnames(newCol) <- paste0("Log of ", input$var)
  } 

  else if(input$select2 == "different") {
    newCol <- isolate(
      c(1-exp(-(values$df[input$var]/100)))
    )
    newCol <- as.data.frame(newCol)
    colnames(newCol) <- paste0(input$var, "Diff of", input$dr1)
  } 
  ### adding new modified columns to the dataframe ###
  isolate(
    values$d <- dplyr::bind_cols(values$d, newCol)
  )

})

output$table1 <- renderTable({
  d1 <- values$d
  nc <- ncol(d1)

  ### printing the whole dataframe (initial+modified) - skipping ###
  ### the first column of modified values, as it doesn't contain our data ###
  if(input$update == 0) {
    print(data.frame(test_df))
  } else {
    data.frame(values$df, d1[2:nc])
  }
})

}))

但是,当我想要包含第一步时,即在运行应用程序之后上传数据集时,应用程序不会启动,因为现在我指的是可能不会启动的反应性内容'不存在。这是一个更新的代码,具有从您自己的来源上传数据的功能:

library(shiny)

runApp(list(
ui=pageWithSidebar(headerPanel("Adding entries to table"),
                 sidebarPanel(fileInput("file1", "Choose file to upload", accept = c("text/csv", "text/comma-separated-values", "text/tab-separated-values", "text/plain", ".csv",".tsv")), 
                              checkboxInput("header", "Header", TRUE), 
                              radioButtons("sep", "Separator",c(Comma=",",Semicolon=";",Tab="\t"),","), 
                              radioButtons("dec", "Decimal",c(Comma=",",Dot="."),","), 
                              actionButton("Load", "Load the File"),
                              uiOutput("select1"),
                              selectInput("select2", "Choose modification",
                                          choices = c("log", "different"), 
                                          selected = NULL, multiple = F),
                              actionButton("update", "Update Table")),
                 mainPanel(tableOutput("table1"))),

server=function(input, output, session) {

values <- reactiveValues()

### uploading data from external source ###
data1 <- reactive({
  if(input$Load == 0){return()}
  inFile <- input$file1
  if (is.null(inFile)){return(NULL)}

  isolate({ 
    input$Load
    my_data <- read.csv(inFile$datapath, header = input$header, sep = input$sep, stringsAsFactors = FALSE, dec = input$dec)
  })
  my_data
})

### specifing the dataset ###
values$df <- data.frame(data1())
nr <<- nrow(data1())

### this will contain the modified values ###
values$d <- data.frame(1:nr)

### selecting a variable to modify ###
output$select1 <- renderUI({
  nc <- ncol(values$df)
  nam <- colnames(values$df)
  selectInput("var", label = "Select var:",
              choices = c(nam), multiple = F,
              selected = nam[1])
})

### calculations needed for modifactions ###
newEntry <- observeEvent(input$update, {

  if(input$select2 == "log") {
    newCol <- isolate(
      c(log(values$df[input$var]))
    )
    newCol <- as.data.frame(newCol)
    colnames(newCol) <- paste0("Log of ", input$var)
  } 

  else if(input$select2 == "different") {
    newCol <- isolate(
      c(1-exp(-(values$df[input$var]/100)))
    )
    newCol <- as.data.frame(newCol)
    colnames(newCol) <- paste0(input$var, "Diff of", input$dr1)
  } 
  ### adding new modified columns to the dataframe ###
  isolate(
    values$d <- dplyr::bind_cols(values$d, newCol)
  )

})

output$table1 <- renderTable({
  d1 <- values$d
  nc <- ncol(d1)

  ### printing the whole dataframe (initial+modified) - skipping the first ###
  ### column of modified values, as it doesn't contain our data ###
  if(input$update == 0) {
    print(data.frame(test_df))
  } else {
    data.frame(values$df, d1[2:nc])
  }
})

}))

我得到的错误:

.getReactiveEnvironment()$currentContext 中的错误:不允许操作 > 没有活动的反应上下文。 (你试图做一些只能>在反应式表达式或观察者内部完成的事情。)

当然,我错过了关于 Shiny 反应性的一些东西,但我彻底阅读了很多不同的文章、问题等,但找不到这个问题的答案。上传文件本身不是问题,因为在引用其内容之前,当我将反应数据集写入普通变量时,这段代码可以在不同的应用程序中完美运行。但是,当将数据写入values$... 时,我该怎么做呢?或者也许有另一种解决方案可以以这种方式处理来自外部源的反应数据?希望我把一切都说清楚了。

【问题讨论】:

  • req(input$file1) 放在data1 reactive 的开头会有帮助吗?
  • @JohnPaul 不,它没有,应用程序关闭并出现同样的错误。
  • 尝试将您的values$xxx 放在观察者中,当他们在反应式上下文中被注意到时,例如observe({values$df &lt;- data1()})。这里data1() 是反应式的,这就是你的代码不起作用的原因。

标签: r user-input shiny shiny-reactivity


【解决方案1】:

感谢@StéphaneLaurent 的帮助!全局变量nr 仍然存在一些问题,但以下更改使其工作。

首先我指定测试数据,它将在用户加载任何数据之前显示(因此应用程序有一些计算基础,而不是空值): test_df &lt;- data.frame(a = seq(1000, 21000, 1000), b = seq(1:21), c = seq(100, 300, 10)).

然后我在指定反应数据框时使用它,以防没有任何用户输入:

  data1 <- reactive({
  if(input$Load == 0){return(test_df)}
  inFile <- input$file1
  if (is.null(inFile)){return(test_df)}

  isolate({ 
    input$Load
    my_data <- read.csv(inFile$datapath, header = input$header, sep = input$sep, stringsAsFactors = FALSE, dec = input$dec)
  })
  my_data
})

最后我对依赖于其他一些反应变量的变量使用observe 函数:

observe({
  values$df <- data.frame(data1())
  nr <- nrow(data1())
  values$d <- data.frame(1:nr)
})

其余代码不需要任何进一步的更改,应用程序现在可以正常运行。

【讨论】:

    猜你喜欢
    • 2013-12-22
    • 2013-06-20
    • 1970-01-01
    • 2019-08-19
    • 2018-09-02
    • 1970-01-01
    • 2016-02-10
    • 2017-07-27
    • 2017-02-02
    相关资源
    最近更新 更多