R Shiny:未找到对象'输入'

时间:2018-04-05 06:27:44

标签: r shiny

这是来自This Question的后续问题,@ K.Rohde正确回答了这个问题。我无法将UI中的输入作为用户定义函数中的参数调用。以下是完整可重复的闪亮代码:

library(shiny)
library(lubridate)
library(dplyr)

rm(list = ls())

Aging <- function(data, Transaction.Date, Report.Date = Sys.Date()){
  if(missing(Transaction.Date)) stop("You forgot to specify Transaction Date")
  Transaction.Date <- deparse(substitute(Transaction.Date))
  Report.Date <- deparse(substitute(Report.Date))
  data$year <- year(data[,Transaction.Date])
  data$Age <- car::recode(year(data[,Transaction.Date]), paste0("year(", Report.Date, ") = year(", Report.Date, "); year(", Report.Date, ") - 1 = year(", Report.Date, ") - 1; else = paste(year(", Report.Date, ")-2, 'And Prior')"))
  return(data)
}

ui <- fluidPage(

  dateInput("Report.Date", "Enter Cut-off Date"),
  actionButton("Submit", "Submit"),
  dataTableOutput("Aged.Data")

)

server <- function(input, output) {




    Debtors <- eventReactive(input$Submit, {
      data.frame(Names = c("John", "Mary", "Charles", "Peter", "David", "Fabian", "Aggrey", "Elizabeth", "Anthony", "Catherine"), Amount = seq(from = 100000, by = 600, length.out = 10), Transaction.Date = seq.Date(from = as.Date("2016/1/1"), by = "quarter", length.out = 10))
    })


    Aged.Data <- eventReactive(input$Submit, {
      Debtors() %>% Aging(., Transaction.Date, input$Report.Date)
    })



  output$Aged.Data <- renderDataTable(Aged.Data())

}

shinyApp(ui, server)

我得到的错误如下:

in recode term:  else = paste(year(input$Report.Date)-2, 'And Prior')
  message: Error in year(input$Report.Date) : object 'input' not found

这似乎来自我调用我的Aging函数并尝试引用输入$ Report.Date作为参数的部分,即

Aged.Data <- eventReactive(input$Submit, {
      Debtors() %>% Aging(., Transaction.Date, input$Report.Date)

我尝试通过This oneThis one之类的问题在线查找类似的解决方案,虽然错误类似,但解决这些问题的建议方法似乎对这些问题来说是唯一的。

我将非常感谢您的帮助。

约瑟夫。

1 个答案:

答案 0 :(得分:0)

这是由于deparsesubstitute的组合。

让我们用更简单的术语重温你正在做的事情:

a <- function(val) {
  val <- deparse(substitute(val))
  val
}

b <- function() {
  c <- "someVariable"
  a(c)
}

通过此设置,您将获得:

> b()
 [1] "c"

我希望你知道这一点,如果没有,请自己做。您基本上是将调用范围b中的变量名称发送到a的函数范围。这几乎从不你想要在编程中发生什么。

在您的代码示例中,您将一个名为input$Report.Date的变量 name 提供给全局定义的函数Aging,并且希望它将会以正确的方式解释那里。但是,当然,input不是此函数中的对象。

但为什么会这样呢?为什么必须在Aging中解释变量。如果您遗漏deparse(substitute(...)),则不会获得变量名称,而是变量值。你想要的不是其他任何东西。

我敢打赌recode函数应该归咎于你必须知道什么是要解释的代码以及什么只是

所以修复就是放弃

Report.Date <- deparse(substitute(Report.Date))

小额外:如果我是你,我永远不会使用像deparsesubstitute这样的东西,除非确实涉及的代码是纯文本并且必须被解释。

recode似乎也是如此之多,因为它只是掩盖了非常简单的修改,如果没有这种过于复杂的工具,您可以轻松完成这些修改。

如果我是你,我的Aging函数将如下所示:

Aging <- function(data, dateColumnName, reportDate = Sys.Date()){
  if(missing(dateColumnName)) stop("You forgot to specify Transaction Date")

  maxDisplayYear <- year(reportDate) - 2
  data$Age <- year(data[,dateColumnName])
  data$Age[data$Age <= maxDisplayYear ] <- paste(maxDisplayYear, 'And Prior')

  return(data)
}

你可以在你的例子中用

来称呼它
Debtors() %>% Aging("Transaction.Date", input$Report.Date)