首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >R和spark:比较不同地理点之间的距离

R和spark:比较不同地理点之间的距离
EN

Stack Overflow用户
提问于 2019-10-24 11:07:43
回答 2查看 650关注 0票数 2

我正在与纽约市出租车数据组合作。数据集有列,包括日期时间、拾取lat/lon、dropoff lat/lon等。现在,我想反向对lat/lon进行地理编码,以找到区/邻里。

我有两个数据帧。1)第一个数据帧包含了我想用最近的newyork邻域的名称分类的所有点。2)第二个数据帧包含邻域名称和它们的质心。

我给你举个小例子。

df_points_to_classify:点击这里下载原始csv

代码语言:javascript
运行
复制
     longitude   latitude     
         <dbl>      <dbl>
1    -73.99037   40.73470
2    -73.98078   40.72991
3    -73.98455   40.67957 
4    -73.99347   40.71899 

df_neighborhood_names_and_their_centroids:点击这里下载原始csv

代码语言:javascript
运行
复制
            longitude           latitude  neighborhood
                <dbl>              <dbl>         <chr>
1   -73.8472005205491  40.89470517661004     Wakefield 
2  -73.82993910812405  40.87429419303015    Co-op City
3  -73.82780644716419  40.88755567735082   Eastchester 
4  -73.90564259591689 40.895437426903875     Fieldston 

要将单点分配给邻域,我必须计算出从点到每个邻域质心的距离。很明显,这个点属于距离最短的邻域。

预期的输出包括在要分类的点的数据中添加一列,其中包含每个点所属的邻域。

预期产出:

代码语言:javascript
运行
复制
     longitude   latitude  neighborhood
         <dbl>      <dbl>         <chr>
1    -73.99037   40.73470     Fieldston
2    -73.98078   40.72991    Co-op City
3    -73.98455   40.67957        etc...
4    -73.99347   40.71899        etc...

我想使用一种计算效率高的方法,因为我要分类的点的数据库非常大(超过1GB)。由于这个原因,我在R上使用了spark。该文件已经以这种方式加载。

代码语言:javascript
运行
复制
library(sparklyr)
sc <- spark_connect(master = "local")
df_points_to_classify <- spark_read_csv(sc, "D:\df_points_to_classify.csv")

是否可以使用dplr来解决这个问题?

编辑:由于df_points_to_classify$any_variable的结果是NULL,所以这个解决方案在使用spark时不适用

代码语言:javascript
运行
复制
library(spatialrisk)
ans <- purrr::map2_dfr(df_points_to_classify$longitude, 
                       df_points_to_classify$latitude, 
                       ~spatialrisk::points_in_circle(df_neighborhood_names_and_their_centroids, .x, .y, 
                                                      lon = longitude, 
                                                      lat = latitude, 
                                                      radius = 2000000)[1,])
EN

回答 2

Stack Overflow用户

发布于 2019-10-24 13:17:47

我在下面添加了一个使用空间风险包的解决方案。这个包中的关键函数是用C++ (Rcpp)编写的,因此非常快。

首先,加载数据:

代码语言:javascript
运行
复制
df1 <- data.frame(longitude = c(-73.99037, -73.98078, -73.98455, -73.99347), 
                  latitude = c(40.73470, 40.72991, 40.67957, 40.71899))

df2 <- data.frame(longitude = c(-73.8472005205491, -73.82993910812405, -73.82780644716419, -73.90564259591689), 
                  latitude = c(40.89470517661004, 40.87429419303015, 40.88755567735082, 40.895437426903875), 
                  neighborhood = c("Wakefield", "Co-op City", "Eastchester", "Fieldston"))

函数spatialrisk::points_in_circle()从中心点计算半径内的观测值。请注意,距离是使用Haversine公式计算的。由于输出的每个元素都是数据框架,所以使用purrr::map_dfr将它们绑定在一起:

代码语言:javascript
运行
复制
ans <- purrr::map2_dfr(df1$longitude, 
                       df1$latitude, 
                       ~spatialrisk::points_in_circle(df2, .x, .y, 
                                                      lon = longitude, 
                                                      lat = latitude, 
                                                      radius = 2000000)[1,])


cbind(df1, ans)

 longitude latitude longitude latitude neighborhood distance_m
1 -73.99037 40.73470 -73.90564 40.89544    Fieldston   19264.50
2 -73.98078 40.72991 -73.90564 40.89544    Fieldston   19483.54
3 -73.98455 40.67957 -73.90564 40.89544    Fieldston   24933.59
4 -73.99347 40.71899 -73.90564 40.89544    Fieldston   20989.84
票数 1
EN

Stack Overflow用户

发布于 2019-10-26 02:13:48

这里有一个完整的解决方案,不是最有效率的,而是基于我的机器估计的。表约90分钟为1200万开始的地点。

是的,这可以使效率更高,但如果这是一次运行,设置它,忘记,然后回来为结果。要提高效率,一个可能的选择是将位置圈到小数点3或4位,并且只查找唯一位置的位置,然后将结果返回到原始数据。

代码语言:javascript
运行
复制
library(readr)
library(dplyr)
library(stringr)

#read tax data in
taxi<-read_csv("yellow.csv")
#Removed unneeded columns (reduces memory requirements and improves speed)
taxi <- taxi %>% select( c(2:7, 10, 11, 13, 16 ))
#filter out rows that have bad data (far outside expected area)
taxi <- taxi %>% filter(pickup_longitude  > -75 & pickup_longitude  < -70)
taxi <- taxi %>% filter(dropoff_longitude  > -75 & dropoff_longitude  < -70)
taxi <- taxi %>% filter(pickup_latitude  > 35 & pickup_latitude  < 45)
taxi <- taxi %>% filter(dropoff_latitude  > 35 & dropoff_latitude  < 45)

point_class<-taxi[1:200000,]  #reduce the sized of the starting vector for testing

#read neighborhood data and clean up data
df_neighborhood<-read.csv("NHoodNameCentroids.csv", stringsAsFactors = FALSE)
location<-str_extract(df_neighborhood$the_geom, "[-0-9.]+ [-0-9.]+")
location<-matrix(as.numeric(unlist(strsplit(location, " "))), ncol=2, byrow=TRUE)
df_neighborhood$longitude<- location[,1]
df_neighborhood$latitude <- location[,2]
df_neighborhood<-df_neighborhood[, c("OBJECTID", "Name", "Borough", "longitude", "latitude")]

#find closest neighbor to starting location
library(geosphere)
start<-Sys.time()
#preallocate the memory to store the result
neighborhood<-vector(length=nrow(point_class)) 
for (i in 1:nrow(point_class)) {
  distance=distGeo(point_class[i,5:6], df_neighborhood[,4:5])
  neighborhood[i]<-which.min(distance)
}

point_class$neighorhood<-df_neighborhood$Name[neighborhood]
point_class
print(Sys.time()-start)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58540031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档