R-如何重组按要素级别划分为原始数据框架的列表



我有一些跟踪数据,我想在其中计算每个点之间的时间差:

# 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秒),则

i希望在新功能中使用这些时间差来拆分轨道,并使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

实际上您的操作有三个步骤:

  • 通过ID
  • 将您的数据分组
  • 计算组中每个时间戳之间的时间差(第一次差异是NA)
  • 创建一个新的ID,该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

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

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

最新更新