使用非常大的数据集分析 R 中两点之间的空间数据

Posted

技术标签:

【中文标题】使用非常大的数据集分析 R 中两点之间的空间数据【英文标题】:Analyzing spatial data between two points in R using a very large data set 【发布时间】:2020-06-19 03:51:43 【问题描述】:

这是我第一次在 R 中从头开始编写代码,我正在为如何处理它而苦苦挣扎。我正在查看龟巢及其与光源(即房屋、灯杆等)的距离,以确定光源在巢的给定半径内的频率。

这些都是非常大的数据集(数十万行),因此代码可能需要为每个嵌套位置运行一个循环。两个数据集的 GPS 坐标都是十进制度。

巢数据主要是纬度、经度、观测日期和物种(如果已知)

光源数据是纬度、经度、类型以及我想保留在数据集中的其他几个与光相关的参数。

任何关于如何循环嵌套坐标以确定半径 r 内的光源的建议,将不胜感激!对于嵌套的 r 中的每个光源,如果可能的话,我希望最终结果吐出整行光源数据(类型、位置、其他与光相关的参数等),而不仅仅是说T 与 F 在 r 内有多少个值。谢谢!

> Nest <- read.csv("Nest.csv", header=T)
> Lights <- read.csv("Lights.csv", header=T)
> #Nest
> dput(droplevels(Nest[1:10, ]))
structure(list(LAT = c(34.146535, 34.194585, 34.216854, 34.269901, 
34.358718, 34.37268, 34.380848, 34.394183, 34.410384, 34.415077
), LONG = c(-77.839787, -77.804013, -77.787032, -77.742722, -77.63655, 
-77.619872, -77.609373, -77.591654, -77.568456, -77.561256), 
    DATE = structure(c(2L, 3L, 4L, 5L, 6L, 8L, 9L, 10L, 1L, 7L
    ), .Label = c("2016-05-19T03:12", "2016-05-21T07:23", "2016-05-23T08:14", 
    "2016-05-24T04:21", "2016-05-25T11:15", "2016-05-27T05:12", 
    "2016-05-27T09:45", "2016-05-28T09:42", "2016-05-28T10:18", 
    "2016-05-29T02:26"), class = "factor"), SPECIES = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Cc", class = "factor")), row.names = c(NA, 
10L), class = "data.frame")
> #Lights
> dput(droplevels(Lights[1:10, ]))
structure(list(LAT = c(34.410925, 34.410803, 34.410686, 34.410476, 
34.410361, 34.410237, 34.410151, 34.410016, 34.409821, 34.409671
), LONG = c(-77.568183, -77.568296, -77.568478, -77.568757, -77.568915, 
-77.569135, -77.569355, -77.569527, -77.569707, -77.569905), 
    DATE = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
    ), .Label = "5/19/2016", class = "factor"), TYPE = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "R", class = "factor"), 
    WATTS = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), row.names = c(NA, 
10L), class = "data.frame")

【问题讨论】:

这个问题对于这个论坛来说有点模糊。我们倾向于不鼓励诸如“任何建议...”之类的提示讨论的内容-还有其他论坛。我们喜欢专注于可以用代码回答的具体问题。为此,您能否在您的问题中附加一些示例数据?每个数据集中的几行,以有效的 R 语法提供,会让你的问题在这里更容易回答。 (dput() 可能非常有用,例如,dput(droplevels(your_data[1:10, ])) 用于前 10 行)。 您的描述非常好,但更多的上下文可能会有所帮助 - 例如,如果您的数据是纬度/经度,那么有很好的软件包可以计算点之间的大圆距离。但是,对于像您这样的大数据,这些比较可能会很昂贵。我假设您的点彼此非常接近,因此欧几里德距离近似可能已经足够好,而且效率更高。您想要一个基于距离的非 equi 连接,这可能最好使用 data.table 包来完成。但是如果没有示例,很难提供更多细节。 @GregorThomas 感谢您的回复!我按照你的建议添加了一些代码来显示数据集的样本(我在编写代码时已经将它分解为一个子集,这样事情就比我运行整个数据集更快)。光源数据彼此非常接近,但巢穴位置更加分散。如果还有什么有用的,请告诉我。 【参考方案1】:

正如您所说,您的数据集很大,建议的解决方案试图避免所有 Nest 与所有 Lamps 之间的完整笛卡尔积。 为此,我们使用data.table 的非等值连接可能性,它只允许像&gt;&lt; 这样的简单运算符。 这允许在巢周围的盒子中制作第一个灯过滤器。 此框应足够大,以包含到 Nest 最大距离的圆圈。 第二步,我们计算过滤后数据的距离(比所有数据的笛卡尔积计算量要少得多):

library(data.table)
library(geosphere)

#To data.table
setDT(Nest)
setDT(Lights)

# Define a box around each nest
dlon<- 0.001
dlat <- 0.001

Nest[,c("LATNest","LONGNest","latmin","latmax","longmin","longmax"):=.(LAT,LONG,LAT-dlat, LAT+dlat,LONG-dlon,LONG+dlon)]
Nest[,c("LAT","LONG") :=.(NULL,NULL)]

# Search lights in box
LightNearNest <- Nest[Lights, .(LATNest,LONGNest, LATLight = LAT, LONGLight = LONG), on = .(latmin<LAT , latmax>LAT,longmin<LONG,longmax>LONG),nomatch=0,allow.cartesian=T]     


# Calculate distance 
LightNearNest[,dist:= geosphere::distHaversine(cbind(LONGNest,LATNest),cbind(LONGLight,LATNest))]
LightNearNest

    LATNest  LONGNest LATLight LONGLight      dist
1: 34.41038 -77.56846 34.41092 -77.56818 25.072269
2: 34.41038 -77.56846 34.41080 -77.56830 14.694370
3: 34.41038 -77.56846 34.41069 -77.56848  2.020476
4: 34.41038 -77.56846 34.41048 -77.56876 27.643784
5: 34.41038 -77.56846 34.41036 -77.56892 42.154475
6: 34.41038 -77.56846 34.41024 -77.56914 62.359234
7: 34.41038 -77.56846 34.41015 -77.56936 82.563993

【讨论】:

感谢您的回复,这真的很有帮助!有没有办法在巢穴位置周围定义一个圆圈而不是一个盒子? 据我所知,一个圆圈会很困难,因为连接表达式只接受简单的运算符。请参阅我的编辑以获取更多说明 编辑发布:告诉我您是否在大型数据集上成功 太好了,感谢您的反馈!因此,首先使用每个巢周围的框只是一种将数据集过滤为更易于管理的方式,以便在后续代码段中围绕每个巢周围的圆/笛卡尔积?另外,当您将纬度和经度的框设置为 0.001 时,单位度数是多少? 确切地说,我们不是计算所有巢和所有灯之间的所有距离,而是只计算围绕一个巢的盒子中的灯的距离:计算量要少得多。盒子的大小以度为单位,我取了 0.001,因为 geosphere::distHaversine(c(0,0),c(0.001,0.001))~160m,这使得离巢的最大距离为 80m,对我来说似乎很明智。您当然可以根据需要增加盒子的大小。

以上是关于使用非常大的数据集分析 R 中两点之间的空间数据的主要内容,如果未能解决你的问题,请参考以下文章

在R中聚类非常大的数据集

R语言用贝叶斯层次模型进行空间数据分析|附代码数据

R语言用贝叶斯层次模型进行空间数据分析|附代码数据

使用空数据集的Spark SQL连接会导致更大的输出文件大小

更有效地显示非常大的数据集

R语言分析协变量之间的非线性关系