【问题标题】:How do I recombine a list split by factor level to the original dataframe?如何将按因子级别拆分的列表重新组合到原始数据框?
【发布时间】:2016-12-20 15:55:59
【问题描述】:

我有一些跟踪数据,我想计算每个点之间的时间差,我可以这样做:

# prep the data
ID = c(rep("A",5), rep("B",5))
DateTime = c("2014-09-25 08:39:45", "2014-09-25 08:39:48", "2014-09-25 08:40:44", "2014-09-25 09:04:00","2014-09-25 09:04:10", "2014-09-25 08:33:32", "2014-09-25 08:34:41", "2014-09-25 08:35:24", "2014-09-25 09:04:00", "2014-09-25 09:04:09")
speed = c(1:10)
df = data.frame(ID,DateTime,speed, stringsAsFactors = FALSE)
df$DateTime<-as.POSIXct(df$DateTime, tz = "UTC")

# function to calculate time differences 
timeCheck<-function(df) {
  sapply(1:(nrow(df) - 1), function(i){
    timeDiff<- difftime(df$DateTime[i+1], df$DateTime[i], units = "sec" )
    return(timeDiff)
  })
}
# preserve order of factor levels 
df$ID <- factor(df$ID, levels=unique(df$ID))

# apply the function by ID
timeDiffData<-sapply(split(df, df$ID), timeCheck)

我希望能够将时间差的新列添加到原始数据帧,但当然这个列表的长度不同,因为该函数不会计算与自身的时间差。

然后,如果差异大于某个值(例如 100 秒),我想在新函数中使用这些时间差异来拆分轨道,并让 ID 反映这一点。

所以最后我的 ID 列有 4 个级别,并且当时间差大于 100 秒时会发生拆分。

生成的数据框应如下所示:

# what it should look like 
ID = c(rep("A",3),rep("A1",2) , rep("B",3), rep("B1",2))
DateTime = c("2014-09-25 08:39:45", "2014-09-25 08:39:48", "2014-09-25 08:40:44", "2014-09-25 09:04:00","2014-09-25 09:04:10", "2014-09-25 08:33:32", "2014-09-25 08:34:41", "2014-09-25 08:35:24", "2014-09-25 09:04:00", "2014-09-25 09:04:09")
speed = c(1:10)
timeDiff<-c(NA,3,56,1396,10,NA,69,43,1716,9)
newdf = data.frame(ID,DateTime,speed,timeDiff, stringsAsFactors = FALSE)
newdf$DateTime<-as.POSIXct(df$DateTime, tz = "UTC")
newdf

【问题讨论】:

    标签: r function datetime time lapply


    【解决方案1】:

    真的你的操作分为三个步骤:

    • 按 ID 对数据进行分组
    • 计算组中每个时间戳之间的时间差(第一个时间差为 NA)
    • 创建一个新 ID,用于计算之前较大的时间间隔数(例如 > 100 秒)

    这可以通过dplyr 非常简单地完成,使用group_by 进行分组,使用mutate 计算每个组内的新变量:

    library(dplyr)
    df %>%
      group_by(ID) %>%
      mutate(timeDiff = c(NA, difftime(tail(DateTime, -1), head(DateTime, -1), units="sec"))) %>%
      mutate(newID = paste0(ID, cumsum(!is.na(timeDiff) & timeDiff > 100))) %>%
      ungroup()
    # A tibble: 10 × 5
    #       ID            DateTime speed timeDiff newID
    #    <chr>              <dttm> <int>    <dbl> <chr>
    # 1      A 2014-09-25 08:39:45     1       NA    A0
    # 2      A 2014-09-25 08:39:48     2        3    A0
    # 3      A 2014-09-25 08:40:44     3       56    A0
    # 4      A 2014-09-25 09:04:00     4     1396    A1
    # 5      A 2014-09-25 09:04:10     5       10    A1
    # 6      B 2014-09-25 08:33:32     6       NA    B0
    # 7      B 2014-09-25 08:34:41     7       69    B0
    # 8      B 2014-09-25 08:35:24     8       43    B0
    # 9      B 2014-09-25 09:04:00     9     1716    B1
    # 10     B 2014-09-25 09:04:09    10        9    B1
    

    【讨论】:

      【解决方案2】:

      作者删除了一个完美的答案。这是为了后代:

      library(data.table)
      setDT(df)[ , ID2 := paste0(ID, cumsum(c(0, diff(DateTime)) > 100)), by = ID]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-14
        • 1970-01-01
        • 1970-01-01
        • 2013-10-20
        • 2020-10-08
        • 2021-08-01
        相关资源
        最近更新 更多