¿Convertir GeoDataFrame de coordenadas x, y en cadenas de líneas usando GROUPBY?

8

Tengo un marco de datos de coordenadas X, Y que representan puntos a lo largo de los caminos tomados por varias entidades diferentes. Pseudo-datos aquí, pero es más o menos de la forma:

entity_id   lat   lon   time

1001        34.5  14.2  4:55 pm
1001        34.7  14.5  4:58 pm
1001        35.0  14.6  5.03 pm

1002        27.1  19.2  2:01 pm
1002        27.4  19.3  2:08 pm
1002        27.4  19.9  2:09 pm

Lo que me gustaría hacer es agrupar estos puntos entity_idy luego organizarlos secuencialmente a tiempo para crear un LineStringobjeto para cada uno entity_id. La salida será de varias líneas / rutas, cada una correspondiente a un entity_id.

Puedo hacer esto recorriendo cada entity_iduno de los puntos entity_idy usando las instrucciones proporcionadas aquí , pero ¿hay alguna forma más rápida / eficiente de hacer esto aprovechando GeoPandas o Shapely, tal vez con groupby?

atkat12
fuente

Respuestas:

16

Creo que encontré una solución provisional, que estoy publicando en caso de que sea útil para alguien:

import pandas as pd
import numpy as np
from geopandas import GeoDataFrame
from shapely.geometry import Point, LineString

# Zip the coordinates into a point object and convert to a GeoDataFrame
geometry = [Point(xy) for xy in zip(df.lon, df.lat)]
df = GeoDataFrame(df, geometry=geometry)

# Aggregate these points with the GroupBy
df = df.groupby(['entity_id'])['geometry'].apply(lambda x: LineString(x.tolist()))
df = GeoDataFrame(df, geometry='geometry')

Tenga en cuenta que si tiene trayectorias de un solo punto en sus datos, primero deberá descartarlas o LineString arrojará un error.

Esto y esta publicación fueron útiles para escribir la función GroupBy.


Actualización : si no descartó el punto único, también puede usar la oración condicional como:

 df = df.groupby(['entity_id'])['geometry'].apply(lambda x: LineString(x.tolist()) if x.size > 1 else x.tolist())
atkat12
fuente
¡esto es increíble!
Ovnis
En caso de que solo desee el conjunto de datos agrupados y mantener la ID como una columna, esto debería ayudar:df.groupby('entity_id', as_index=False).agg({'geometry': lambda x: ...})
Ufos