为什么在使用ifelse后我必须再次设置as.Date原点?有没有更好的办法?

时间:2010-12-06 10:41:44

标签: r date

以下功能确实有效,但最后一个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

1 个答案:

答案 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"