es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cuáles son las formas de calcular conjuntos de distancias en R para Big Data?

Problema: Necesitamos un método de big data para calcular distancias entre puntos. Planteamos a continuación lo que nos gustaría hacer con un dataframe de cinco observaciones. Sin embargo, este método en particular no es factible cuando el número de filas es grande (>1 millón). En el pasado, hemos utilizado SAS para realizar este tipo de análisis, pero preferiríamos utilizar R si es posible. (Nota: No voy a mostrar el código porque, aunque describo una forma de hacer esto con conjuntos de datos más pequeños a continuación, este método es básicamente imposible de utilizar con datos en nuestra escala.)

Comenzamos con un dataframe de tiendas, cada una con una latitud y longitud (aunque este no es un archivo espacial, ni queremos utilizar un archivo espacial).

<h1>Puedes pensar en x e y en este ejemplo como coordenadas cartesianas</h1>

tiendas <- data.frame(id = 1:5,
                     x = c(1, 0, 1, 2, 0),
                     y = c(1, 2, 0, 2, 0))

tiendas
  id x y
1  1 1 1
2  2 0 2
3  3 1 0
4  4 2 2
5  5 0 0

Para cada tienda, queremos saber la cantidad de tiendas dentro de una distancia x. En un dataframe pequeño, esto es sencillo. Creamos otro dataframe con todas las coordenadas, lo fusionamos de nuevo, calculamos las distancias, creamos un indicador si la distancia es menor que x y sumamos los indicadores (restando uno para la propia tienda, que se encuentra a una distancia de 0). Esto resultaría en un conjunto de datos que se vería así:

   id x y  s1.dist  s2.dist  s3.dist  s4.dist  s5.dist
1:  1 1 1 0.000000 1.414214 1.000000 1.414214 1.414214
2:  2 0 2 1.414214 0.000000 2.236068 2.000000 2.000000
3:  3 1 0 1.000000 2.236068 0.000000 2.236068 1.000000
4:  4 2 2 1.414214 2.000000 2.236068 0.000000 2.828427
5:  5 0 0 1.414214 2.000000 1.000000 2.828427 0.000000

Cuando consideramos (arbitrariamente) como “cercano” aquello que está por debajo de 1.45, obtenemos indicadores que se ven así:

id x y s1.close s2.close s3.close s4.close s5.close close.total
1:  1 1 1        1        1        1        1        1           4
2:  2 0 2        1        1        0        0        0           1
3:  3 1 0        1        0        1        0        1           2
4:  4 2 2        1        0        0        1        0           1
5:  5 0 0        1        0        1        0        1           2

El producto final debería verse así:

id close.total
1:  1           4
2:  2           1
3:  3           2
4:  4           1
5:  5           2

Se agradece cualquier consejo.

Muchas gracias.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Un método escalable para calcular distancias entre puntos en big data es utilizar el paquete geosphere en R. El paquete incluye una función llamada distm que calcula distancias entre dos conjuntos de coordenadas utilizando varios métodos, como Haversine, Vincenty y Great Circle.

    Para aplicar este método al ejemplo dado, primero necesitamos crear una matriz de coordenadas utilizando la función cbind:

    coord <- cbind(stores$x, stores$y)
    

    Luego, podemos utilizar distm para calcular las distancias entre todos los pares de coordenadas:

    library(geosphere)
    dist_matrix <- distm(coord)
    

    La matriz resultante dist_matrix tendrá distancias en metros de forma predeterminada, pero la unidad se puede cambiar utilizando el argumento distUnit.

    Para encontrar el número de tiendas dentro de una distancia x para cada tienda, podemos aplicar un umbral en dist_matrix y contar el número de entradas por debajo del umbral (excluyendo la diagonal). Aquí está el código para hacer eso:

    thresh <- 1450 # en metros
    close_stores <- apply(dist_matrix, 1, function(x) sum(x < thresh) - 1)
    

    El vector resultante close_stores tendrá el número de tiendas dentro del umbral dado para cada tienda. Podemos combinarlo con la columna id en el dataframe original para obtener la salida final:

    output <- data.frame(id = stores$id, total.close = close_stores)
    

    Este método debería ser escalable para conjuntos de datos grandes con millones de filas, siempre y cuando haya suficiente memoria para almacenar la matriz de distancia entre pares. Si la memoria se convierte en un problema, existen métodos alternativos como el uso de índices espaciales o dividir el conjunto de datos en fragmentos más pequeños.

Comments are closed.