这是来自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 one和This one之类的问题在线查找类似的解决方案,虽然错误类似,但解决这些问题的建议方法似乎对这些问题来说是唯一的。
我将非常感谢您的帮助。
约瑟夫。
答案 0 :(得分:0)
这是由于deparse
和substitute
的组合。
让我们用更简单的术语重温你正在做的事情:
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))
小额外:如果我是你,我永远不会使用像deparse
和substitute
这样的东西,除非确实涉及的代码是纯文本并且必须被解释。
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)