Transformer GeoDataFrame des coordonnées x, y en Linestrings en utilisant GROUPBY?

8

J'ai une trame de données de coordonnées X, Y qui représentent des points le long des chemins empruntés par plusieurs entités différentes. Des pseudo-données ici, mais elles sont à peu près de la forme:

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

Ce que je voudrais faire, c'est regrouper ces points par entity_id, puis organiser les points séquentiellement dans le temps pour créer un LineStringobjet pour chacun entity_id. La sortie sera de plusieurs lignes / chemins, chacun correspondant à un entity_id.

Je peux le faire en parcourant chaque entity_idpoint entity_idet en utilisant les instructions fournies ici , mais existe-t-il un moyen plus rapide / plus efficace de tirer parti de GeoPandas ou Shapely, peut-être avec groupby?

atkat12
la source

Réponses:

16

Je pense que j'ai trouvé une solution provisoire, que je poste au cas où cela serait utile pour n'importe qui:

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

Notez que si vous avez des trajectoires à un seul point dans vos données, vous devrez d'abord les supprimer ou LineString générera une erreur.

Ceci et ce post ont été utiles pour écrire la fonction GroupBy.


Mise à jour : si vous n'avez pas supprimé le point unique, vous pouvez également utiliser la phrase conditionnelle comme:

 df = df.groupby(['entity_id'])['geometry'].apply(lambda x: LineString(x.tolist()) if x.size > 1 else x.tolist())
atkat12
la source
c'est étonnant!
Ufos
Dans le cas où vous souhaitez uniquement l'ensemble de données groupé et conserver l'ID en tant que colonne, cela devrait aider:df.groupby('entity_id', as_index=False).agg({'geometry': lambda x: ...})
Ufos