【问题标题】:Join dataframes by time intervals R按时间间隔 R 连接数据帧
【发布时间】:2018-04-26 20:26:12
【问题描述】:

我有一个数据框,其中包含被 GPS 项圈跟踪的个人。为了检查这些人是独立在那里运动还是相互跟随,我想将一个人的每个点(每一行)与围绕第一个点每隔 12 小时间隔的其他人的每个点相关联,然后计算例如,它们之间的距离小于 100 m。

我的数据框:Data_real

 'data.frame':  57471 obs. of  7 variables:
$ Elephant         : Factor w/ 17 levels "Bull","Bull (one tusk)",..: 1 1 1 1 1 
$ Date.time        : POSIXct, format: "2015-10-06 14:38:00" "2015-10-06 18:37:00" "2015-10-06 22:37:00" "2015-10-07 02:37:00" ...
$ Date        : POSIXct, format: "2015-10-06" "2015-10-06"
$ Date_month       : chr  "2015-10" "2015-10" "2015-10" "2015-10" ...
$ Date.time_plus6h : POSIXct, format: "2015-10-06 20:38:00" "2015-10-07 
$ Date.time_minus6h: POSIXct, format: "2015-10-06 08:38:00" "2015-10-06 
$ coords.x1        : num  329468 329393 328341 327563 327271 ...
$ coords.x1.1      : num  329468 329393 328341 327563 327271 ...


Elephant             Date.time coords.x1 coords.x1.1 Date_month    Date.time_plus6h   Date.time_minus6h
0     Bull 2015-10-06 14:38:00  329467.6    329467.6    2015-10 2015-10-06 20:38:00 2015-10-06 08:38:00
1     Bull 2015-10-06 18:37:00  329392.5    329392.5    2015-10 2015-10-07 00:37:00 2015-10-06 12:37:00
2     Bull 2015-10-06 22:37:00  328341.3    328341.3    2015-10 2015-10-07 04:37:00 2015-10-06 16:37:00
3     Bull 2015-10-07 02:37:00  327562.9    327562.9    2015-10 2015-10-07 08:37:00 2015-10-06 20:37:00
4     Bull 2015-10-07 06:37:00  327271.0    327271.0    2015-10 2015-10-07 12:37:00 2015-10-07 00:37:00
5     Bull 2015-10-07 14:38:00  322977.5    322977.5    2015-10 2015-10-07 20:38:00 2015-10-07 08:38:00

起初,我试图通过 Date 来 inner_join ,然后计算每个已连接的点之间的距离。

Association<-NA
for (id in unique(Data_real$Elephant)) {
id1<-Data_real[Data_real$Elephant == id,] #one individual
id2<-Data_real[Data_real$Elephant != id,] #all the others

all.id<-inner_join(id2,id1,by="Date")
deltaX<-(all.id$coords.x2.y - all.id$coords.x2.x) ^ 2   
deltaY<-(all.id$coords.x1.y - all.id$coords.x1.x) ^ 2
all.id$distance<-sqrt (deltaX + deltaY) #distance in meters 

Association1<-rbind(Association1, all.id) 

Data_real<-Data_real[Data_real$Elephant != id,] 

}

这样的问题是,如果一个人在 23h55 有一个点,它可能与第二天的点比同一天的点更相关,这就是为什么我想使用每个点周围的时间间隔来消除这种偏见。我搜索,我认为加入功能不能做到这一点。在这个论坛的另一个问题上,他们建议使用过滤器,我对我的数据进行了尝试。它也不是完美的,因为月份的开始和结束时的点关联可能会出现偏差,但它比按天好...

all.id<-inner_join(id2,id1,by="Date_month")
all.id<-as_tibble(all.id)
all.id2<-filter(all.id,Date.time.y >= Date.time_moins6.x & Date.time.y <= 
Date.time_plus6.x) 

主要问题是该命令似乎无法按照我的编码方式运行,或者完成时间太长。

我在不同的论坛上阅读,我发现 data.table 包中的函数可能对我有用,但我仍然不明白它是如何进行的,我不确定它是否适用于同一种操作。

所以我的问题是:您现在是否是一种连接两个数据框的好方法,您希望将一个人的每个点与第一点时间前后 +6/-6 小时的所有其他人的每个点相关联?如果可能,不要像我尝试的那样,因为我们在月底和月初仍然有偏差值。

提前感谢您的帮助! :)

【问题讨论】:

标签: r join filter


【解决方案1】:

对此的钝器解决方案是先进行笛卡尔积或交叉连接,然后进行过滤。

我可能会考虑类似于以下内容(注意,这不是运行代码的保证,您没有提供可重现的示例)

基本上,将您的总数据分成 17 个子数据帧,每头大象一个。然后,得到两只大象的每一种组合。接下来,编写一个函数,对任意两只大象进行笛卡尔积,并且只保留“y”大象在“x”大象的 6 小时窗口内的行。使用 map2 传递成对的大象并将它们绑定在一起。现在,我们过滤了数据,所以我们没有实际的位置数据,所以我们需要重新加入其余的数据。然后你就可以做剩下的事情了。

library(dplyr)
each_elephant = split(Data_real,Data_real$Elephant)
pairs = expand.grid(x = levels(Data_real$Elephant), 
                    y = levels(Data_real$Elephant))
fuzzyJoin = function(e1,e2){
  df1 = each_elephant[[e1]] %>% select("Elephant.x" = Elephant,
                       "Date.time.x" = Date.time,
                       Date.time_plus6h,
                       Date.time_minus6h)
  df2 = each_elephant[[e2]] %>% select("Elephant.y" = Elephant,
                       "Date.time.y" = Date.time)
  totalDF = tidyr::crossing(df1,df2)
  totalDF %<>%
    filter(Date.time.y >= Date.time_minus6h & Date.time.y <= Date.time_plus6h)
  return(totalDF)
}
output = do.call(bind_rows,purrr::map2(pairs$x,pairs$y,fuzzyJoin)) %>%
  left_join(Data_real, by=c("Elephant.x"="Elephant","Date.time.x"="Date.time")) %>%
  left_join(Data_real,by=c("Elephant.y"="Elephant","Date.time.y"="Date.time"))

【讨论】:

  • 感谢您的帮助!
  • @AJBérubé 如果答案有帮助,请考虑接受并点赞。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-02
  • 2014-06-17
  • 1970-01-01
  • 2011-05-07
  • 2021-05-07
  • 1970-01-01
  • 2016-07-17
相关资源
最近更新 更多