Transformando GeoDataFrame de coordenadas x, y em linhas de cadeia usando GROUPBY?

8

Eu tenho um quadro de dados de coordenadas X, Y que representam pontos ao longo dos caminhos percorridos por várias entidades diferentes. Pseudo-dados aqui, mas é aproximadamente da 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

O que eu gostaria de fazer é agrupar esses pontos entity_ide, em seguida, organizar os pontos sequencialmente no tempo para criar um LineStringobjeto para cada um entity_id. A saída será de várias linhas / caminhos, cada um correspondendo a um entity_id.

Eu posso fazer isso percorrendo cada entity_idponto entity_ide usando as instruções fornecidas aqui , mas existe uma maneira mais rápida / eficiente de fazer isso utilizando GeoPandas ou Shapely, talvez com groupby?

atkat12
fonte

Respostas:

16

Acho que encontrei uma solução provisória, que estou publicando, caso seja útil para qualquer pessoa:

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

Observe que se você tiver trajetórias de ponto único em seus dados, precisará descartá-las primeiro ou o LineString gerará um erro.

Esta e esta postagem foram úteis para escrever a função GroupBy.


Atualização : se você não descartou o ponto único, também pode usar a sentença condicional como:

 df = df.groupby(['entity_id'])['geometry'].apply(lambda x: LineString(x.tolist()) if x.size > 1 else x.tolist())
atkat12
fonte
isso é incrível!
Ufos
Caso você queira apenas o conjunto de dados agrupado e mantenha o ID como uma coluna, isso deve ajudar:df.groupby('entity_id', as_index=False).agg({'geometry': lambda x: ...})
Ufos