Why after using ifelse should I set as.Date origin again? Is there a better way?

The following function works, but the last part of as.Date was more or less the result of trial and error, which are not entirely clear.

### 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) } 

Instead, I tried to do it like this (because it was more intuitive for me):

 { .... ifelse(get(period) == 13,eval(y),eval(x)) return(resDate) } 

This returned corrected values ​​whenever the condition was FALSE (no), but NA was returned if the condition was TRUE (yes). Why is this? And if I use the above function, why do I need to determine the origin again? Why do I still have a call to. Give again?

EDIT:

  a <- rep(2002:2010,2) b <- rep(1:13,2) d<-cbind(a,b[1:length(a)]) names(d) <- c("year_col","period_col") 

PS: I found this thread on an ifelse vector.

+2
r code-review
source share
1 answer

Your design is at least “interesting.” For starters, neither x nor y produce the result. I wonder why you are using assignment in your eval() . this gives you the resDate vector, which is what the last call was. And it does not depend on the condition, this is the last one written ( eval(x) in your case). They are executed before the ifelse clause is executed.

Plus, the output you get is a numerical representation of your data, not a data object. That is, in resDate. I suppose ifelse cannot define the class of the output vector when you use eval() inside. I am surprised that you get the output at all, in fact you are effectively using something that can be called an “error” in R (Microsoft would call it a function :-)).

Your error in your ifelse: get(period) does not exist. it should be get(period, dframe) . Then it works. The only reason this works on your computer is because you are supposedly using period in your workspace. Classis problem while debugging.

In any case, I would do this:

 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="")) } 

It is a little faster than your own, has fewer errors and conversions, and it is rather an R-way to do it. You can change the year [...] and period [...] according to ifelse constructs, but using indexes is usually faster.


EDIT:

It is easier to generate data:

 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" 
+2
source share

All Articles