Question

I'd like to augment a zoo object with a variable which I could use to test for month changes. I'm sure there are more general ways to do this. Suggestions there would be great, but I'd like to understand why this simple approach fails. I'd feel better if I understood what I'm missing here ;-)

e.g. for a zoo object

library(zoo)
tz <- structure(c(7L, 7L, 1L, 6L, 0L, 9L, 0L, 1L, 6L, 0L, 3L, 3L, 5L, 
0L, 8L, 2L, 0L, 3L, 2L, 5L, 2L, 3L, 4L, 7L, 8L, 9L, 0L, 1L, 4L, 
5L, 6L, 7L, 8L, 2L, 3L, 4L, 5L, 8L, 9L, 0L), .Dim = c(20L, 2L
), .Dimnames = list(NULL, c("x", "y")), index = structure(c(13880, 
13881, 13913, 13916, 13946, 13947, 13948, 13980, 13983, 13984, 
13985, 14016, 14048, 14082, 14083, 14115, 14147, 14180, 14212, 
14243), class = "Date"), class = "zoo")

Add a year/month variable using as.yearmon() seems easy enough. If I were in a data frame this would yield a fine character variable, but in zoo tragedy ensues if you forget to wrap in as.numeric()

tz$yrmo <- as.numeric(as.yearmon(index(tstz)))
> head(tz)
           x y     yrmo
2008-01-02 7 2 2008.000
2008-01-03 7 3 2008.000
2008-02-04 1 4 2008.083
2008-02-07 6 7 2008.083
2008-03-08 0 8 2008.167
2008-03-09 9 9 2008.167

This looks great and I can compare data elements successfully

(tz$x[6] != tz$y[6])
2008-03-09
FALSE

but why do I get this result when I compare the year/month variable?

> (tz$yrmo[2] != tz$yrmo[1])
Data:
logical(0)

Index:
character(0)

and why does testing the yearmon or data items with identical() fail in this way? (both should be true)

> identical(tz$yrmo[2] , tz$yrmo[1])
[1] FALSE
> identical(tz$x[2] , tz$x[1])
[1] FALSE

Am I just playing with fire in using yearmon() which creates an index class in zoo? Should I switch to something like Dirk Eddelbuettel's 'turning a date into a monthnumber'? Number of months between two dates

Was it helpful?

Solution

Q1: The clue in the output having a Data and a Index section is that these are zoo objects. So they have Index attributes that are compared as well and they are not equal. If you wanted to compare the values then you could access the coredata():

> (coredata(tz$yrmo[2]) != coredata(tz$yrmo[1]))
[1] FALSE
> coredata(tz$yrmo[2])
[1] 2008
> coredata(tz$yrmo[1])
[1] 2008

Q2: identical checks more than just the numeric values. It also determines equality of all attributes.

> attributes(tz$yrmo[2])
$index
[1] "2008-01-03"

$class
[1] "zoo"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top