【问题标题】:Expand a time series by specified time lengths in R在 R 中按指定的时间长度扩展时间序列
【发布时间】:2013-07-18 10:49:07
【问题描述】:

我想根据 POSIXct 格式的日期时间列在 R 中扩展数据框。我的数据框中的每一行日期时间(列 [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

我很难找到一种简单的方法来执行此处理任务,并且对类似问题的回答无法为我提供解决此问题的方法(即How to convert 10-minute time blocks to 1-minute intervals in RExpand Categorical Column in a Time Series to Mulitple Per Second Count Columns)。我认为split()merge()ddply() 之类的函数可能会有所帮助,但我无法解决。我还在学习,所以任何建议将不胜感激。

【问题讨论】:

  • +1 是一个很好的可重现示例

标签: r datetime expand posixct


【解决方案1】:

您可以使用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

【讨论】:

    【解决方案2】:

    可能有更简单的方法,但我希望这会很快:

    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
    

    【讨论】:

    • 感谢您的回答。这也很有效!非常感谢。
    最近更新 更多