Выравнивание нескольких объектов зоопарка одновременно в R
Рассмотрим следующие объекты зоопарка:
x <- data.frame(Date = seq(as.Date("2013-02-01"), length=6, by="1 month") - 1, x = seq(6))
y <- data.frame(Date = seq(as.Date("2013-02-01"), length=4, by="1 month"), y = seq(4))
z <- data.frame(Date = seq(as.Date("2012-11-01"), length=9, by="1 month"), z = seq(9))
x.zoo = zoo(x[,-1], order.by = x[,1])
y.zoo = zoo(y[,-1], order.by = y[,1])
z.zoo = zoo(z[,-1], order.by = z[,1])
Обратите внимание, что 3 объекта зоопарка имеют различную длину. Я хотел бы выровнять все объекты относительно даты переменной "x": другими словами, я хочу создать новый фрейм данных, который содержит столбец Date (индекс объекта x), и заполнить для каждой переменной ближайший доступное наблюдение.
Вот результат, который я ищу:
Date x y z
1 2013-01-31 1 1 4
2 2013-02-28 2 2 5
3 2013-03-31 3 3 6
4 2013-04-30 4 4 NA
5 2013-05-31 5 NA NA
6 2013-06-30 6 NA NA
Обратите внимание, что на самом деле у меня есть 10 переменных, которые я хочу выровнять по x. Я в курсе функции na.locf
от zoo
пакет, но я не уверен, как адаптировать его в контексте нескольких объектов зоопарка.
Могу ли я сделать это эффективно?
Спасибо!
2 ответа
Попробуй это:
xx.zoo <- aggregate(x.zoo, as.yearmon)
yy.zoo <- aggregate(y.zoo, as.yearmon)
zz.zoo <- aggregate(z.zoo, as.yearmon)
out <- merge(x = xx.zoo, y = yy.zoo, z = zz.zoo, all = c(TRUE, FALSE, FALSE))
или если вы не хотите писать это:
L <- setNames(list(x.zoo, y.zoo, z.zoo), c("x", "y", "z"))
all. <- c(TRUE, rep(FALSE, length(L) - 1)) # all FALSE except first
out <- do.call(merge, c(lapply(L, aggregate, as.yearmon), all = list(all.)))
который дает:
> out
x y z
Jan 2013 1 NA 3
Feb 2013 2 1 4
Mar 2013 3 2 5
Apr 2013 4 3 6
May 2013 5 4 1
Jun 2013 6 NA 2
Время года может быть предпочтительнее, но если для вас важно, чтобы время было таким же, как x.zoo
Затем добавьте это:
time(out) <- time(x.zoo)
ОБНОВЛЕНИЕ: Незначительные улучшения.
Альтернатива, используя предложение @Ricardo Saporta о round_date
:
library(lubridate)
# round dates in x.zoo to nearest month
index(x.zoo) <- round_date(index(x.zoo), "month")
# merge
xyz <- merge(x = x.zoo, y = y.zoo, z = z.zoo, all = c(TRUE, FALSE, FALSE))
# make data frame from original x dates and data from zoo object
data.frame(Date = x$Date, coredata(xyz))
# Date x y z
# 1 2013-01-31 1 1 4
# 2 2013-02-28 2 2 5
# 3 2013-03-31 3 3 6
# 4 2013-04-30 4 4 7
# 5 2013-05-31 5 NA 8
# 6 2013-06-30 6 NA 9