Reputation: 1101
data.frame
recycles shorter vectors to match the length of the data frame.
test1 = data.frame(x = 1:5, date = as.Date("2013-05-01"))
x date
1 1 2013-05-01
2 2 2013-05-01
3 3 2013-05-01
4 4 2013-05-01
5 5 2013-05-01
However, it does not seem to work with the chron
class:
require(chron)
test2 = data.frame(x = 1:5, time = times("08:00:00"))
Error in data.frame(x = 1:5, time = times("08:00:00")) :
arguments imply differing number of rows: 5, 1
There are workarounds, e.g. doing the recycling manually, like:
test3 = data.frame(x = 1:5, time = times(rep("08:00:00",5)))
But why doesn't the recycling work? Am I missing something here or is there a bug somewhere?
Upvotes: 1
Views: 82
Reputation: 7396
The documentation for data.frame
notes:
Objects passed to data.frame should have the same number of rows, but atomic vectors (see is.vector), factors and character vectors protected by I will be recycled a whole number of times if necessary (including as elements of list arguments).
If you look at the source for data.frame
, you can actually see the check for is.vector
.
So the question is, is your times
object a vector? The answer's no:
is.vector(times("8:00:00"))
# [1] FALSE
Why is this? ?is.vector
tells us a little more:
is.vector returns TRUE if x is a vector of the specified mode having no attributes other than names. It returns FALSE otherwise.
If you take a closer look at your times
object, you can see that it does indeed have a non-names attribute:
str(times("8:00:00"))
# Class 'times' atomic [1:1] 0.333
# ..- attr(*, "format")= chr "h:m:s"
Interestingly, Date
objects aren't vectors either, but data.frame
makes an exception.
So, in the end, maybe the recycling rule is actually the recycling exception, at least in the case of data.frame
. As you've already figured out though, a workaround is easy enough.
Upvotes: 2