如何将按因子级别拆分的列表重新组合到原始数据帧?

时间:2016-12-20 15:55:59

标签: r function datetime time lapply

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

<activity
        android:name="com.journeyapps.barcodescanner.CaptureActivity"
        android:screenOrientation="portrait"
        tools:replace="screenOrientation" />

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

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

所以最后我的ID列有4个级别,当时差为&gt;时会发生拆分。 100秒

结果数据框应如下所示:

# 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)

2 个答案:

答案 0 :(得分:0)

真的,你的操作有三个步骤:

  • 按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

答案 1 :(得分:0)

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

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