Mengubah GeoDataFrame dari x, y koordinat ke Linestrings menggunakan GROUPBY?

8

Saya memiliki kerangka data koordinat X, Y yang mewakili titik di sepanjang jalur yang diambil oleh beberapa entitas yang berbeda. Pseudo-data di sini, tetapi kira-kira berbentuk:

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

Apa yang ingin saya lakukan adalah mengelompokkan poin-poin ini entity_id, dan kemudian mengatur poin secara berurutan dalam waktu untuk membuat LineStringobjek untuk masing-masing entity_id. Output akan terdiri dari beberapa baris / jalur, dengan masing-masing sesuai dengan entity_id.

Saya dapat melakukan ini dengan mengulangi entity_idsetiap titik entity_iddan menggunakan instruksi yang disediakan di sini , tetapi apakah ada cara yang lebih cepat / lebih efisien untuk melakukan ini dengan meningkatkan GeoPandas atau Shapely, mungkin dengan groupby?

atkat12
sumber

Jawaban:

16

Saya pikir saya menemukan solusi sementara, yang saya posting jika berguna bagi siapa pun:

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

Perhatikan bahwa jika Anda memiliki lintasan titik tunggal dalam data Anda, Anda harus membuang ini terlebih dahulu atau LineString akan melempar kesalahan.

Ini dan posting ini sangat membantu dalam menulis fungsi GroupBy.


Pembaruan : Jika Anda tidak membuang satu titik pun, Anda juga dapat menggunakan kalimat kondisional seperti:

 df = df.groupby(['entity_id'])['geometry'].apply(lambda x: LineString(x.tolist()) if x.size > 1 else x.tolist())
atkat12
sumber
Itu mengagumkan!
Ufos
Jika Anda hanya menginginkan dataset yang dikelompokkan dan menyimpan ID sebagai kolom, ini akan membantu:df.groupby('entity_id', as_index=False).agg({'geometry': lambda x: ...})
Ufos