2

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

Community
  • 1
  • 1
BobH
  • 235
  • 2
  • 5

1 Answers1

3

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"
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • That's very helpful--answers both questions & shows how to make things work. – BobH Sep 05 '11 at 19:08
  • And I guess the first test I did (tz$x[6] != tz$y[6]) which appeared to work correctly, depended on my having compared two values which arbitrarily had identical indexes. It would have failed had I tried (tz$x[2] != tz$y[4]) where the values equal, but indexes differ. – BobH Sep 05 '11 at 19:13