R и искра: сравнить расстояние между различными географическими точками - PullRequest
2 голосов
/ 24 октября 2019

Я работаю с набором данных такси Нью-Йорка. В наборе данных есть столбцы, включающие дату и время, широта / долгота захвата, широта / долгота и т. Д. Теперь я хочу изменить геокодирование широты / долготы, чтобы найти район / район.

У меня есть два кадра данных. 1) Первый фрейм данных содержит все точки, которые я хочу классифицировать с названием ближайшей окрестности Нью-Йорка. 2) Второй фрейм данных содержит названия окрестностей и их центроиды.

Я покажу вам небольшой пример.

df_points_to_classify: Нажмите здесь, чтобы загрузить оригинальный csv

     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

            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 

Чтобы назначить одну точку окрестности, я должен рассчитать расстояние от точки до центра тяжести каждой окрестности,Очевидно, что точка будет принадлежать окрестности с кратчайшим расстоянием.

Ожидаемый результат состоит из добавления столбца к кадру данных классифицируемых точек, содержащего окрестность, которой принадлежит каждая точка.

ожидаемый результат:

     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...

Я хотел бы использовать вычислительно эффективный метод, потому что база данных моих точек для классификации очень большая (более одного гигабайта). По этой причине я использую искру на R. Файл был загружен таким образом.

library(sparklyr)
sc <- spark_connect(master = "local")
df_points_to_classify <- spark_read_csv(sc, "D:\df_points_to_classify.csv")

Можно ли использовать dplr для решения этой проблемы? Я получу лучший ответ с 10 долларами в BTC

РЕДАКТИРОВАТЬ: это решение не применяется при использовании свечи, потому что результат df_points_to_classify$any_variable равен NULL

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,])

Ответы [ 2 ]

1 голос
/ 24 октября 2019

Я добавляю ниже решение с использованием пакета пространственного риска. Ключевые функции в этом пакете написаны на C ++ (Rcpp) и, следовательно, очень быстрые.

Сначала загрузите данные:

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"))

Функция пространственныйrisk: points_in_circle () вычисляетнаблюдения в радиусе от центральной точки. Обратите внимание, что расстояния рассчитываются по формуле Haversine. Поскольку каждый элемент выходных данных является фреймом данных, purrr :: map_dfr используется для связывания их вместе:

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
0 голосов
/ 26 октября 2019

Вот полное решение, не обязательно самое эффективное, но основанное на моей машине. таблица около 90 минут для 12 миллионов стартовых локаций.
Да, это может быть сделано более эффективно, но если это однократный прогон;установить его, забыть и вернуться позже для результатов. Одним из возможных способов сделать это более эффективным является округление местоположений до 3 или 4 десятичных знаков и поиск местоположения только для уникальных местоположений, а затем присоединение результатов к исходному кадру данных.

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)
...