首页 > 解决方案 > 在一个数据帧中按时间间隔在另一个数据帧中创建中断:模糊连接

问题描述

我在 df2 中记录了 CO2,并在 d 中列出了实验开始和结束时间:

data.framedf2包含随时间推移的连续 CO2 测量值。

df2<-data.frame(CO2.ppm.=sample(300:500,72,replace=TRUE),Dev.Date.Time=seq(
     from=as.POSIXct("2012-1-1 0:00", tz="BST"),
     to=as.POSIXct("2012-1-3 23:00", tz="BST"),
     by="hour"
   ) )

我有一个data.frame df1名为: 的连续时间变量Dev.Date.Time,一个名为的列ExperimentID并记录了它的类型ExperimentType。请注意,有一段时间没有进行任何实验,但不需要将其删除。

df1<-data.frame(ExperimentID=rep(1:12,each=6),ExperimentType=rep(c("IV","NoExperiment","Obs"),each=24),Dev.Date.Time=seq(
     from=as.POSIXct("2012-1-1 0:00", tz="BST"),
     to=as.POSIXct("2012-1-3 23:00", tz="BST"),
     by="hour"
   ) )

然后,我创建了另一个 data.frame d,其中包含每个实验的开始和结束时间。

startTime<-aggregate(data=df1,Dev.Date.Time~ExperimentID+ExperimentType,head,1)
endTime<-aggregate(data=df1,Dev.Date.Time~ExperimentID+ExperimentType,tail,1)

d<-inner_join(startTime, endTime, by=c("ExperimentID","ExperimentType"))

我想根据我在 d 中找到的开始和停止时间在 df2 中创建一个名为 ExperimentID 的列和另一个名为 ExperimentType 的列

我正在尝试以下使休息的方法,但我不知道如何使标签匹配。任何想法都非常感谢。

最初我考虑使用cut. 虽然它取得了我想要的突破,但我并没有更接近用 ExperimentID 标记它们。

breakz <- as_tibble(lubridate::ymd_hms(d$Dev.Date.Time.x,d$Dev.Date.Time.y))
    breakz<-dplyr::arrange(breakz,value)
    df1$ActivityID<-cut(df1$Dev.Date.Time,breaks=unique(breakz$value), labels = c(d$ExperimentID,d$ExperimentType)

编辑:

根据评论中的建议,我正在尝试模糊连接,因为实际上时间戳并不完全匹配。所以我需要按间隔合并。

要求(模糊连接)

df3<-(fuzzy_right_join(
  d, df2,
  by = c(
    "StartTime" = "Dev.Date.Time",
    "EndTime" = "Dev.Date.Time"
  ),
  match_fun = list( `>=`, `<=`)
))

在所有 df3$ExperimentID 中产生 NA。有什么想法吗?

标签: rdplyrfuzzyjoin

解决方案


这很有效,而且速度很快!抱怨时区,但似乎还可以

从:

https://www.r-bloggers.com/in-between-a-rock-and-a-conditional-join/

library(data.table)
  # Attempt #4: Use the data.table package
  myDataDT <- data.table(df2)
  myDataDT[, SomeValueHelp := Dev.Date.Time]
  linkTableDT <- data.table(d)
  setkey(linkTableDT, StartTime, EndTime)
  
  df3 <- foverlaps(myDataDT, linkTableDT, by.x=c('Dev.Date.Time', 'SomeValueHelp'), 
                      by.y=c('StartTime', 'EndTime'))
  
  df3[sample(nrow(df3), 3),]

推荐阅读