Наружный продукт с датами - PullRequest
2 голосов
/ 03 ноября 2011

Учитывая вектор значений даты и времени, мне нужно было создать data.frame, содержащее дату и время в 0:10 часах после каждой исходной даты / времени - первый столбец через 0 часов, второй столбец через 1 час и т. Д.

У меня возникли проблемы с поиском способа сделать это легко с помощью lubridate. Я думал, что это должно работать:

rt <- ymd_hms(c("2011-11-03 19:24:12", "2011-10-28 20:48:21",
  "2011-11-04 10:06:14", "2011-10-31 17:10:05", "2011-10-28 06:35:59"))
result <- outer(rt, hours(0:10), "+")

Но различные части этого трубопровода выходят из строя. В конечном итоге я получаю эту ошибку:

Error in FUN(X[[1L]], ...) : invalid 'times' argument

, который, кажется, происходит из-за неспособности rep.POSIXct() или rep.period() обрабатывать аргумент не 101-длины times. Или что-то.

И это, вероятно, в любом случае не сработало бы, потому что outer() возвращает матрицу, и объекты даты, даже даты POSIXct (которые внутренне являются просто целыми числами), кажется, не могут быть элементами в матрице.

То, что я выяснил, что это сработало (просто чтобы получить время, а не помещать их в кадр данных), после примерно 10 других догадок, было так:

with_tz(do.call(c, lapply(rt, function(x) x+hours(0:3))), tz(rt[1]))

Необходимо добавить with_tz(), поскольку c() теряет атрибут часового пояса. Я также должен сделать do.call(c, lapply(...)), а не просто sapply(...), потому что sapply() теряет тот факт, что это дата.

Возможно, другой альтернативой было бы создание фрейма данных с помощью do.call(cbind, ...) или чего-то еще.

В общем, было бы замечательно, если бы каждый раз, когда мы находим R задачи даты / времени, которые кажутся концептуально простыми, но требуют большой гимнастики, прежде чем найти решение, мы могли бы устранить препятствия, внеся изменения в lubridate или что-то еще , Я думаю, что это может быть одним из тех времен. =)

1 Ответ

4 голосов
/ 03 ноября 2011

Это не использует outer(), но я думаю, что это приведет вас туда, куда вы хотите. Это действительно использует plyr.

library("lubridate")
library("plyr")

rt <- ymd_hms(c("2011-11-03 19:24:12", "2011-10-28 20:48:21",
  "2011-11-04 10:06:14", "2011-10-31 17:10:05", "2011-10-28 06:35:59"))

offsets = 0:10
names(offsets) <- offsets

dat <- data.frame(llply(offsets, function(offset){rt+hours(offset)}))

При присвоении имен переменной offsets имена столбцов data.frame становятся лучше.

> str(dat)
'data.frame':   5 obs. of  11 variables:
 $ X0 : POSIXct, format: "2011-11-03 19:24:12" "2011-10-28 20:48:21" ...
 $ X1 : POSIXct, format: "2011-11-03 20:24:12" "2011-10-28 21:48:21" ...
 $ X2 : POSIXct, format: "2011-11-03 21:24:12" "2011-10-28 22:48:21" ...
 $ X3 : POSIXct, format: "2011-11-03 22:24:12" "2011-10-28 23:48:21" ...
 $ X4 : POSIXct, format: "2011-11-03 23:24:12" "2011-10-29 00:48:21" ...
 $ X5 : POSIXct, format: "2011-11-04 00:24:12" "2011-10-29 01:48:21" ...
 $ X6 : POSIXct, format: "2011-11-04 01:24:12" "2011-10-29 02:48:21" ...
 $ X7 : POSIXct, format: "2011-11-04 02:24:12" "2011-10-29 03:48:21" ...
 $ X8 : POSIXct, format: "2011-11-04 03:24:12" "2011-10-29 04:48:21" ...
 $ X9 : POSIXct, format: "2011-11-04 04:24:12" "2011-10-29 05:48:21" ...
 $ X10: POSIXct, format: "2011-11-04 05:24:12" "2011-10-29 06:48:21" ...

UPDATE:

Комментарий Кена о ldply() против data.frame(llply()) заставил меня осознать, что есть другой способ приблизиться к этому.

dat <- ldply(rt, `+`, hours(0:10))

что дает

> str(dat)
'data.frame':   5 obs. of  11 variables:
 $ V1 : POSIXct, format: "2011-11-03 12:24:12" "2011-10-28 13:48:21" ...
 $ V2 : POSIXct, format: "2011-11-03 13:24:12" "2011-10-28 14:48:21" ...
 $ V3 : POSIXct, format: "2011-11-03 14:24:12" "2011-10-28 15:48:21" ...
 $ V4 : POSIXct, format: "2011-11-03 15:24:12" "2011-10-28 16:48:21" ...
 $ V5 : POSIXct, format: "2011-11-03 16:24:12" "2011-10-28 17:48:21" ...
 $ V6 : POSIXct, format: "2011-11-03 17:24:12" "2011-10-28 18:48:21" ...
 $ V7 : POSIXct, format: "2011-11-03 18:24:12" "2011-10-28 19:48:21" ...
 $ V8 : POSIXct, format: "2011-11-03 19:24:12" "2011-10-28 20:48:21" ...
 $ V9 : POSIXct, format: "2011-11-03 20:24:12" "2011-10-28 21:48:21" ...
 $ V10: POSIXct, format: "2011-11-03 21:24:12" "2011-10-28 22:48:21" ...
 $ V11: POSIXct, format: "2011-11-03 22:24:12" "2011-10-28 23:48:21" ...

Обратите внимание, что в дополнение к различным именам столбцов (V1-V11, а не X0-X10) эти даты были преобразованы в местное время (в моем случае PDT):

> dat$V1
[1] "2011-11-03 12:24:12 PDT" "2011-10-28 13:48:21 PDT"
[3] "2011-11-04 03:06:14 PDT" "2011-10-31 10:10:05 PDT"
[5] "2011-10-27 23:35:59 PDT"
...