Расширить временной ряд на указанные отрезки времени в R

Я хотел бы расширить фрейм данных в R на основе столбца datetime в формате POSIXct. Каждая строка времени (столбец [1]) в моем фрейме данных в настоящее время представляет начало временного блока. Длина временного блока в секундах указана в столбце [2]. Я хотел бы расширить фрейм данных, чтобы дать отдельную отметку времени (строку) для каждой секунды в этом временном блоке, как указано в столбце 2.

Вот несколько примеров данных:

structure(list(datetime = structure(1:5, .Label = c("14/04/2013 17:42:29", 
"14/04/2013 17:43:49", "14/04/2013 17:43:58", "14/04/2013 17:44:03", 
"14/04/2013 17:44:11"), class = "factor"), duration = c(1L, 5L, 
2L, 3L, 2L), mean = c(1.17, 2.36, 1.05, 1.43, 1.47)), .Names = c("datetime", 
"duration", "mean"), class = "data.frame", row.names = c(NA, 
-5L))

Вот что у меня сейчас есть:

             datetime duration mean
  14/04/2013 17:42:29        1 1.17
  14/04/2013 17:43:49        5 2.36
  14/04/2013 17:43:58        2 1.05
  14/04/2013 17:44:03        3 1.43
  14/04/2013 17:44:11        2 1.47

Вот что хотелось бы в итоге:

             datetime duration mean
  14/04/2013 17:42:29        1 1.17
  14/04/2013 17:43:49        1 2.36
  14/04/2013 17:43:50        1 2.36
  14/04/2013 17:43:51        1 2.36
  14/04/2013 17:43:52        1 2.36
  14/04/2013 17:43:53        1 2.36
  14/04/2013 17:43:58        1 1.05
  15/04/2013 17:43:59        1 1.05
  14/04/2013 17:44:03        1 1.43
  14/04/2013 17:44:04        1 1.43
  14/04/2013 17:44:05        1 1.43
  14/04/2013 17:44:11        1 1.47
  14/04/2013 17:44:12        1 1.47

У меня возникли проблемы с поиском простого способа выполнения этой задачи обработки, и ответы на похожие вопросы не дают мне решения этой проблемы (например, Как преобразовать 10-минутные временные блоки в 1-минутные интервалы в R, Расширить категориальный столбец во временном ряду до нескольких раз в секунду Счетчик столбцов). Я думаю, что функции типа split(), merge() и ddply() могут помочь, но я не могу с этим справиться. Я все еще учусь, поэтому будем благодарны за любые предложения.


person Emily    schedule 18.07.2013    source источник
comment
+1 за хороший воспроизводимый пример   -  person Simon O'Hanlon    schedule 18.07.2013


Ответы (2)


Вы можете использовать lapply для создания data.frame для каждого сегмента, а затем rbind все результаты вместе в конце, вот так ...

res <- lapply( 1:nrow(df) , function(x){ data.frame(
    datetime = strptime( df[ x , 1 ] , format = "%d/%m/%Y %H:%M:%S" ) +  ( seq_len( df[ x , 2 ] ) - 1 ) ,
    duration = rep( 1 , df[ x , 2 ] ) ,
    mean = rep( df[ x , 3 ] ,  df[ x , 2 ] ) ) } )

do.call( rbind , res )
#             datetime duration mean
#1  2013-04-14 17:42:29        1 1.17
#2  2013-04-14 17:43:49        1 2.36
#3  2013-04-14 17:43:50        1 2.36
#4  2013-04-14 17:43:51        1 2.36
#5  2013-04-14 17:43:52        1 2.36
#6  2013-04-14 17:43:53        1 2.36
#7  2013-04-14 17:43:58        1 1.05
#8  2013-04-14 17:43:59        1 1.05
#9  2013-04-14 17:44:03        1 1.43
#10 2013-04-14 17:44:04        1 1.43
#11 2013-04-14 17:44:05        1 1.43
#12 2013-04-14 17:44:11        1 1.47
#13 2013-04-14 17:44:12        1 1.47
person Simon O'Hanlon    schedule 18.07.2013

Возможно, есть более простой способ, но я надеюсь, что он будет довольно быстрым:

DF$datetime <- as.POSIXct(DF$datetime, format="%d/%m/%Y %H:%M:%S", tz="GMT")

inverse.rle2 <- function(values,lengths) {
  #conserve class and attributes
  #so it plays well with date-time classes
  class.values <- class(values)
  attributes.values <- attributes(values)

  res <- rep.int(values, lengths)

  #assign class and attributes
  class(res) <- class.values
  attributes(res) <- attributes.values
  res
}

#use the function by looping over the columns
DF2 <- do.call(cbind.data.frame, lapply(DF[,-2], inverse.rle2, lengths=DF[,2]))
#add seconds to runs
DF2$datetime <- DF2$datetime + 
                do.call(c,
                        tapply(c(0,diff(DF2$datetime)==0), 
                               DF2$datetime, cumsum))

#              datetime mean
#1  2013-04-14 17:42:29 1.17
#2  2013-04-14 17:43:49 2.36
#3  2013-04-14 17:43:50 2.36
#4  2013-04-14 17:43:51 2.36
#5  2013-04-14 17:43:52 2.36
#6  2013-04-14 17:43:53 2.36
#7  2013-04-14 17:43:58 1.05
#8  2013-04-14 17:43:59 1.05
#9  2013-04-14 17:44:03 1.43
#10 2013-04-14 17:44:04 1.43
#11 2013-04-14 17:44:05 1.43
#12 2013-04-14 17:44:11 1.47
#13 2013-04-14 17:44:12 1.47
person Roland    schedule 18.07.2013
comment
спасибо за Ваш ответ. Это тоже прекрасно работает! Очень признателен. - person Emily; 18.07.2013