[英]How do I recombine a list split by factor level to the original dataframe?
I have some tracking data where I want to calculate the time difference between each point which I can do with this: 我有一些跟踪数据,我想在此计算每个点之间的时间差:
# 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)
I want to be able to add a new column of the time differences to the original dataframe but of course this list is a different length, because the function doesn't calculate the time difference from itself. 我希望能够将时差的新列添加到原始数据帧,但是此列表的长度当然是不同的,因为该函数不会根据自身计算时差。
I then want to use these time differences in a new function to split the tracks if the difference is greater than a certain value (say 100 seconds for the sake of example) and have the ID reflect this. 然后,我想在一个新函数中使用这些时差,如果时差大于某个值(例如,举例来说为100秒),则分割轨道,并让ID反映出来。
So in the end I'd have 4 levels for my ID column and the split would occur when the time difference is > 100 seconds. 因此,最后我将为我的ID列设置4个级别,并且当时差> 100秒时将发生拆分。
The resulting dataframe should look something like: 产生的数据框应类似于:
# 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
Really your operation has three steps: 确实,您的操作包含三个步骤:
This can be done pretty simply with dplyr
, using group_by
for the grouping and mutate
for computing new variables within each group: 这可以使用
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
One answer that worked perfectly was deleted by the author. 作者删除了一个效果最佳的答案。 Here it is for posterity:
这里是给后代的:
library(data.table)
setDT(df)[ , ID2 := paste0(ID, cumsum(c(0, diff(DateTime)) > 100)), by = ID]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.