8

I have zoo objects that look like:

head(obs)

      Index pp
1932-01-01  0
1932-01-02  0.2
1932-01-03  0

and I want to split the index into 3 columns (years, months and days in separate columns) so I can do some analyses per day of month using ddply.

I don't know if it makes any difference but my dates were created using:

dates <- as.Date(CET[,1], "%d-%m-%Y")
obs <- xts(CET[,2], dates)

where CET is the original file with dates in column 1 and pp in column 2.

Thanks for helping!

sbg
  • 1,772
  • 8
  • 27
  • 45

4 Answers4

17

1) columns. We can use lubridate's year/month/day or chron's month.day.year:

1a) columns via lubridate

library(zoo)
z <- zoo(1:1000, as.Date("1932-01-01") + 0:999)

library(lubridate)
tt <- time(z)
zz <- cbind(z, year = year(tt), month = month(tt), day = day(tt))

1b) columns via chron

library(zoo)
z <- zoo(1:1000, as.Date("1932-01-01") + 0:999)

library(chron)
zz <- with(month.day.year(time(z)), zoo(cbind(z, day, month, year)))

2) aggregate. However, we do not really need to create columns in the first place. We can just use aggregate.zoo directly with the original zoo object, z, using lubridate or chron or just using yearmon from zoo depending on what it is that you want to do:

2a) aggregate using lubridate

library(zoo)
z <- zoo(1:1000, as.Date("1932-01-01") + 0:999)

library(lubridate)
aggregate(z, day, mean)
aggregate(z, month, mean)
aggregate(z, year, mean)

2b) aggregate using chron

library(zoo)
z <- zoo(1:1000, as.Date("1932-01-01") + 0:999)

library(chron)
mdy <- month.day.year(time(z))

aggregate(z, mdy$day, mean)
aggregate(z, mdy$month, mean)
aggregate(z, mdy$year, mean)

# or
ct <- as.chron(time(z))

aggregate(z, days(ct), mean)
aggregate(z, months(ct), mean)
aggregate(z, years(ct), mean)

# days(ct) and years(ct) can actually
# be shortened to just days and years within the above context
# (and that would work for months too except they would be out of order)
aggregate(z, days, mean)
aggregate(z, years, mean)

2c) aggregate using yearmon

If we wish to summarize each year/month rather than lumping all January months together, all February months together, etc. then we need neither chron nor lubridate but rather can use zoo's yearmon:

library(zoo)
z <- zoo(1:1000, as.Date("1932-01-01") + 0:999)

aggregate(z, yearmon, mean)
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
7
dtstr <- as.character( index(CET))

CET$yr <- sapply(strsplit(dtstr, "-") , "[", 1)
CET$mon <- sapply(strsplit(dtstr, "-") , "[", 2)
CET$dt <- sapply(strsplit(dtstr, "-") , "[", 3)
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • thanks DWin, `index(CET)` doesn't work (`Error: could not find function "Index"`) but changing to `dtstr <- as.character( CET[,1])`, works! – sbg Jul 01 '11 at 17:25
  • 1
    Glad it got you where you need. Note: The function is spelled `index`, not `Index` – IRTFM Jul 01 '11 at 17:49
5

You can try:

CET$year <- format(CET[,1], "%Y") # year
CET$month <- format(CET[,1], "%m") # month
CET$day <- format(CET[,1], "%d") # day
Manuel Ramón
  • 2,490
  • 2
  • 18
  • 23
  • 1
    thanks but it doesn't work: `Error in format.default(structure(as.character(x), names = names(x), dim = dim(x), : invalid 'trim' argument` – sbg Jul 01 '11 at 16:45
  • 2
    It seems like your dates were factors. You can use the str() function to make sure that you dates are actually dates. – Manuel Ramón Jul 01 '11 at 16:54
2
require(lubridate)
maindata1 <- cbind(maindata1, day=day(maindata1$Date), month=month(maindata1$date), year=year(maindata1$date))
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Arockya
  • 21
  • 1