R 相对于每个点,通过时间和位置窗口重复高效地过滤大型数据集

R 相对于每个点,通过时间和位置窗口重复高效地过滤大型数据集,r,database,R,Database,我有一个由大约5500万条记录组成的数据集,分为多个CSV。每条记录都包含一个日期时间、一个纬度和一个经度,表示闪电事件及其发生的位置。我需要添加一个字段,其中对于每个事件,我需要以秒为单位列出自上次事件在当前事件5海里范围内发生以来的时间。我在下面写的代码在技术上是可行的,但在第一个CSV上花了一个多小时之后,我不得不停止它 虽然我是用R写的,但我愿意使用任何语言或工具来实现我的目标,而不需要几天或几周来处理数据集。我也尝试过SQLite,但到目前为止,在这方面,我只是在尝试让它做数学运算时感

我有一个由大约5500万条记录组成的数据集,分为多个CSV。每条记录都包含一个日期时间、一个纬度和一个经度,表示闪电事件及其发生的位置。我需要添加一个字段,其中对于每个事件,我需要以秒为单位列出自上次事件在当前事件5海里范围内发生以来的时间。我在下面写的代码在技术上是可行的,但在第一个CSV上花了一个多小时之后,我不得不停止它

虽然我是用R写的,但我愿意使用任何语言或工具来实现我的目标,而不需要几天或几周来处理数据集。我也尝试过SQLite,但到目前为止,在这方面,我只是在尝试让它做数学运算时感到沮丧

另外请注意,在此搜索过程中,一些条目将返回NA,因为之前没有任何符合条件的事件。这很好;如果是那样的话,我想要安娜

CSV数据示例遵循代码,我制作了一个包含一天数据的文件,可在以下位置进行测试:

(我现在在下面的代码中使用出租车距离,根据所有记录事件的平均纬度,
0.08335
0.0965
的值在lat/long值中约为5 nmi。如果有一种方法可以快速计算毕达哥拉斯距离,那就太好了。)

代码:

library(dplyr)

#Get list of all relevant CSVs
fList = list.files(pattern = "*.TL.csv")

#Reads in the first CSV; haven't implemented looping through files yet 
t1 = read.csv(as.character(fList[1]), colClasses=c(DateTime="character"))
t1 = t1[order(t1$DateTime),]  #Sort by DateTime
rownames(t1) = NULL  #Reset index

#Used for filtering the current row out of the search
index = c(1:nrow(t1))

#Create empty column
t1$TimeGap = NA

for (i in 2:nrow(t1)) {
  temp = max(filter(t1, (DateTime <= t1$DateTime[i]) &
                        (Latitude >= t1$Latitude[i]-0.08335) &
                        (Latitude <= t1$Latitude[i]+0.08335) &
                        (Longitude >= t1$Longitude[i]-0.0965) &
                        (Longitude <= t1$Longitude[i]+0.0965) &
                        (index != i))$DateTime)
  t1$TimeGap[i] = as.numeric(difftime(as.POSIXct(t1$DateTime[i],format="%Y-%m-%d %H:%M:%OS"),
                                      as.POSIXct(temp,format="%Y-%m-%d %H:%M:%OS"),
                                      units="secs"))
}
"DateTime","Latitude","Longitude"
"2019-05-02 14:43:37.833",26.9517,-81.4851
"2019-05-02 14:43:37.857",26.9674,-81.4758
"2019-05-02 14:43:37.988",26.9802,-81.4698
"2019-05-02 14:45:41.512",27.0024,-81.4612
"2019-05-02 15:22:59.614",27.295,-81.1728
"2019-05-02 15:24:06.284",27.3444,-81.1213
"2019-05-02 15:24:51.607",27.3306,-81.146
"2019-05-02 15:26:52.130",27.5441,-81.1099
"2019-05-02 15:26:52.131",27.3214,-81.1758
"2019-05-02 15:26:52.131",27.3326,-81.1614
"2019-05-02 15:26:52.134",27.5396,-81.0952
"2019-05-02 15:26:52.134",27.5377,-81.1069
"2019-05-02 15:26:52.156",27.517,-81.1147
"2019-05-02 15:26:52.167",27.5377,-81.0962
"2019-05-02 15:28:59.356",27.5156,-81.1152
"2019-05-02 15:28:59.357",27.519,-81.1092
"2019-05-02 15:28:59.359",27.406,-81.174
"2019-05-02 15:28:59.362",27.4081,-81.1489
"2019-05-02 15:28:59.362",27.508,-81.1472
"2019-05-02 15:28:59.364",27.5183,-81.1497
"2019-05-02 15:28:59.417",27.5338,-81.1712
"2019-05-02 15:31:39.021",27.4052,-81.1956
"2019-05-02 15:31:39.027",27.4381,-81.1837
"2019-05-02 15:31:39.027",27.5141,-81.159
"2019-05-02 15:31:39.027",27.417,-81.1631
"2019-05-02 15:31:39.027",27.5439,-81.1326
"2019-05-02 15:31:39.048",27.4809,-81.1691
"2019-05-02 15:31:39.048",27.4666,-81.1561
"2019-05-02 15:31:39.048",27.4666,-81.1561
"2019-05-02 15:31:39.048",27.401,-81.1679

这听起来像是(相对较新的)软件包将脱颖而出的情况。它类似于,但需要考虑大量数据。没有使用过它,但根据我从
data.table
中获得的知识,并假设您的所有数据都在
file.path(getwd(),'data')
中,您可能会使用以下方法实现您的目标

library(disk.frame)
# Setup from the ingesting Data vignette
if(interactive()) { 
  setup_disk.frame()
  # highly recommended, however it is pun into interactive() for CRAN because
  # change user options are not allowed on CRAN
  options(future.globals.maxSize = Inf)  
} else {
  setup_disk.frame(2)
}
# Import csv data from shared folder
disk.f <- csv_to_disk.frame(list.files(file.path(getwd(), 'data'), full.names = TRUE))
免责声明! 我无法测试上面的代码,因此它很可能被拼写错误和错误的连接所困扰(我的聚合组应该是
rowid
还是
rowid.I
?我可能已经将其转换为一种方式或另一种方式),以及未在
disk.frame
中测试的自连接(可能需要创建
disk.frame
的副本)。我可能会创建一个更具可复制性的示例,但更可能的是,这可以作为一个起点,并为正确的解决方案奠定基础

注意
disk.frame
同样有一个类似于
dplyr
的接口,可以在
data.table
自连接语法不起作用的情况下使用

更新1:
似乎
data.table
disk.frame
语法是
data.table
宇宙的一个部分包装,因此我建议的连接并没有像预期的那样工作。使用
foverlaps
是目前我快速子集方法的第二个选择。

是的,我看到的唯一方法是使用Rcpp和编译你自己的C++运行循环的函数。在R中超过100K行的任何东西都会遇到内存问题。
disk.f[, `:=`(LatitudeMax = Latitude + 0.08335,
              LatitudeMin = Latitude - 0.08335,
              LongitudeMax = Longitude + 0.0965, 
              LongitudeMin = Longitude - 0.0965,
              rowid = seq_len(.N),
              Datetime = as.POSIXct(Datetime, format = "%Y-%m-%d %H:%M:%OS"))]
# Perform selv join.. I hope I got the direction right here.
calc.disk.f <- 
  disk.f[disk.f[, .(Latitude.i = Latitude, 
                    Longitude.i = Longitute, 
                    Datetime.i = Datetime, 
                    rowid.i = rowid)], 
         on = .(Datetime >= Datetime.i,
                LongitudeMax >= Longitude.i,
                LongitudeMin <= Longitde.i, 
                LatitudeMax >= Latitude.i,
                LatitudeMin <= Latitude.i,
                rowid != rowid.i), 
         allow.cartesian = TRUE][, .(Timegap = difftime(Datetime, 
                                                        max(Datetime.i), 
                                                        units = 'secs')), 
                                 by = rowid]
# Merge result into original frame.
disk.f <- calc_disk_f[disk.f, on = rowid]
# clean up calc.disk.f
delete(calc.disk.f)

# Save result or change to a regular data.table/data.frame/tibble
## Not sure if this is in csv, fst or what format.
write_disk.frame(disk.f, outdir = file.path(getwd(), data, 'result.df'))