以下功能确实有效,但最后一个as.Date部分或多或少是试验和错误的结果,不完全理解。
### This function creates a real date column out of year / period that is saved in
### in separate columns, plus it handles a 13th period in case of overlapping period
### terminology. Turns quarters into months.
realDate <- function (table,year="year_col",period="period_col"){
if (is.character(table) == TRUE)
{
dframe <- get(table)
}
else{
dframe <- table
}
x <- expression({resDate <- with(dframe,
as.Date(paste(get(year),"-",
ifelse(get(period) > 9, get(period),
paste("0", get(period), sep = "")),
"-01", sep = "")))
})
y <- expression({resDate <- with(dframe,as.Date(paste(get(year) + 1,"-","01","-01",sep="")))})
#### I do not get this? Why do I have to do this?
a <- ifelse(get(period) == 13,eval(y),eval(x))
a <-as.Date(a, origin="1970-01-01")
return(a)
}
相反,我尝试这样做(因为它对我来说更直观):
{ ....
ifelse(get(period) == 13,eval(y),eval(x))
return(resDate)
}
每当条件为FALSE(否)时返回校正值,但如果条件为TRUE则返回NA(是)。这是为什么?如果我使用上面的函数,为什么我必须再次定义原点?为什么我甚至再次打电话给.Date?
编辑:
a <- rep(2002:2010,2)
b <- rep(1:13,2)
d<-cbind(a,b[1:length(a)])
names(d) <- c("year_col","period_col")
P.S .: 我在矢量化ifelse上找到了这个thread。
答案 0 :(得分:2)
你的构造至少是“有趣的”。首先,x和y都不给出输出。我想知道你为什么在eval()
中使用作业。这会给你一个resDate向量,它正是最后一次调用的内容。这不取决于条件,它是最后写的(在你的情况下eval(x)
)。它们在ifelse子句执行之前执行。
另外,您获得的输出是数据的数字表示,而不是数据对象。那是resDate。我猜ifelse
无法确定输出向量的类,因为你在里面使用eval()
。我很惊讶你得到输出,实际上你正在有效地使用R中可能被称为“bug”的东西(微软称之为功能:-))。
你的错误在于你的错误:get(period)
不存在。它应该是get(period, dframe)
。然后它工作。它在您的计算机上工作的唯一原因是因为您的工作空间中可能有period
。调试时的Classis问题。
无论如何,我会成功:
realDate <- function (table,year="year_col",period="period_col"){
if (is.character(table)){ # is.character(table) returns a boolean already.
dframe <- get(table)
} else {
dframe <- table
}
year <- get(year,dframe)
period <- get(period,dframe)
year[period==13] <- year[period==13]+1
period[period==13] <- 1
as.Date(paste(year,"-",period,"-01",sep=""))
}
这比你自己的快得多,陷阱和转换次数少,而且更像是R的做法。您可以通过ifelse构造更改年份[...]和期间[...],但使用索引通常会更快。
编辑:
这对于数据生成更容易:
dframe <- data.frame(
year_col= rep(2006:2007,each=13),
period_col = rep(1:13,2)
)
realDate(dframe)
[1] "2006-01-01" "2006-02-01" "2006-03-01" "2006-04-01" "2006-05-01"
"2006-06-01" "2006-07-01" "2006-08-01" "2006-09-01"
[10] "2006-10-01" "2006-11-01" "2006-12-01" "2007-01-01" "2007-01-01"
"2007-02-01" "2007-03-01" "2007-04-01" "2007-05-01"
[19] "2007-06-01" "2007-07-01" "2007-08-01" "2007-09-01"
"2007-10-01" "2007-11-01" "2007-12-01" "2008-01-01"