Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does mapply not return date-objects?

Tags:

r

I have a function that takes a Date-object and returns one. However, when I applied the function to a data.frame column using the mapply function, I ran into problems: I didn't get Date-objects back, as expected, but numbers. Any idea how I could convert those to Date-objects? Also, I would be interested in what's happening here. Help is really appreciated!

Minimal example:

#Define simple function that takes a date-object and returns a date-object
add_day <- function(dat) {return(dat + 1)}

#Set up data.frame with two date-object entries in one column
df <- data.frame(Col_A = c(as.Date("01/01/00", "%m/%d/%y"), as.Date("05/02/11", "%m/%d/%y")))
#That is the desired result: give a date-object to the function, get one back
add_day(df[1, "Col_A"]) #Returns [1] "2000-01-02"
add_day(df[2, "Col_A"]) #Returns [1] "2011-05-03"

#Why does it not work here? What do I get back?
mapply(add_day, df[, "Col_A"]) #Returns [1] 10958 15097; Why? What is that?
like image 241
Christoph_J Avatar asked Oct 08 '11 18:10

Christoph_J


2 Answers

Another option is something like sapply.preserving.attributes:

sapply.preserving.attributes = function(l, ...) {
    r = sapply(l, ...)
    attributes(r) = attributes(l)
    r
}

> sapply.preserving.attributes(dates, add_day)
[1] "2000-01-02" "2011-05-03"
like image 190
Owen Avatar answered Sep 28 '22 01:09

Owen


Your function is returning 'dates', just not in the format you are used to. Dates are stored internally as days since [some fixed date]. (I can't remember off the top of my head which one, and varies slightly by specific format.)

If you wrap your mapply call in as.Date you'll see the output you expect.

To see what's going on here, consider that mapply is using sapply under the hood. So for example:

sapply(df[,1],add_day)
[1] 10958 15097

But remember that sapply by default is unlisting results for convenience. If we specify simplify = FALSE:

sapply(df[,1],add_day,simplify = FALSE)
[[1]]
[1] "2000-01-02"

[[2]]
[1] "2011-05-03"

So when R coerced the list to a vector, the class information is dropped and only the internal storage is retained, namely the number of days since [whatever that specific date is]. And of course, mapply also has a SIMPLIFY argument that acts in the same way.

like image 35
joran Avatar answered Sep 28 '22 00:09

joran