Konvertieren Sie einen Pandas-DataFrame in einen GeoDataFrame

42

Dies scheint eine recht einfache Frage zu sein, aber ich kann nicht herausfinden, wie ein Pandas-DataFrame für eine räumliche Verknüpfung in einen GeoDataFrame konvertiert wird.

Hier ist ein Beispiel für die Verwendung meiner Daten df.head():

    Date/Time           Lat       Lon       ID
0   4/1/2014 0:11:00    40.7690   -73.9549  140
1   4/1/2014 0:17:00    40.7267   -74.0345  NaN

Tatsächlich wurde dieser Datenframe aus einer CSV erstellt. Wenn es also einfacher ist, die CSV direkt als GeoDataFrame einzulesen, ist dies auch in Ordnung.

atkat12
quelle
1
benutze GeoPandas
Gen

Antworten:

78

Konvertieren Sie zuerst den Inhalt des DataFrames (z. B. Latund die LonSpalten) in die entsprechenden Shapely- Geometrien und verwenden Sie sie dann zusammen mit dem ursprünglichen DataFrame, um einen GeoDataFrame zu erstellen.

from geopandas import GeoDataFrame
from shapely.geometry import Point

geometry = [Point(xy) for xy in zip(df.Lon, df.Lat)]
df = df.drop(['Lon', 'Lat'], axis=1)
crs = {'init': 'epsg:4326'}
gdf = GeoDataFrame(df, crs=crs, geometry=geometry)

Ergebnis:

    Date/Time           ID      geometry
0   4/1/2014 0:11:00    140     POINT (-73.95489999999999 40.769)
1   4/1/2014 0:17:00    NaN     POINT (-74.03449999999999 40.7267)

Da die Geometrien häufig im WKT-Format vorliegen, dachte ich, ich würde auch ein Beispiel für diesen Fall hinzufügen:

import geopandas as gpd
import shapely.wkt

geometry = df['wktcolumn'].map(shapely.wkt.loads)
df = df.drop('wktcolumn', axis=1)
crs = {'init': 'epsg:4326'}
gdf = gpd.GeoDataFrame(df, crs=crs, geometry=geometry)
Martin Valgur
quelle
Danke noch einmal! Das ist viel einfacher und läuft sehr schnell - viel besser, als bei n = 500.000 durch jede Zeile des df zu iterieren :)
atkat12
6
Meine Güte, danke! Ich überprüfe diese Antwort wie alle 2 Tage :)
Owen
1
Sie würden denken, dies wäre der erste Eintrag in der Dokumentation!
Dominik
+1 für die shapely.wkt. Ich habe eine Weile gebraucht, um das herauszufinden!
StefanK
14

Einzeiler! Plus einige Leistungsindikatoren für Big-Data-Mitarbeiter.

Bei a pandas.DataFramemit x Längen- und y Breitengrad wie folgt:

df.head()
x   y
0   229.617902  -73.133816
1   229.611157  -73.141299
2   229.609825  -73.142795
3   229.607159  -73.145782
4   229.605825  -73.147274

Lassen Sie uns das konvertieren pandas.DataFramein ein geopandas.GeoDataFramewie folgt:

Bibliotheksimporte und formschöne Beschleunigung :

import geopandas as gpd
import shapely
shapely.speedups.enable() # enabled by default from version 1.6.0

Code + Benchmark-Zeiten auf einem Testdatensatz, den ich rumliegen habe:

#Martin's original version:
#%timeit 1.87 s ± 7.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
gdf = gpd.GeoDataFrame(df.drop(['x', 'y'], axis=1),
                                crs={'init': 'epsg:4326'},
                                geometry=[shapely.geometry.Point(xy) for xy in zip(df.x, df.y)])



#Pandas apply method
#%timeit 8.59 s ± 60.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
gdf = gpd.GeoDataFrame(df.drop(['x', 'y'], axis=1),
                       crs={'init': 'epsg:4326'},
                       geometry=df.apply(lambda row: shapely.geometry.Point((row.x, row.y)), axis=1))

Die Verwendung pandas.applyist überraschend langsam, passt jedoch möglicherweise besser zu einigen anderen Workflows (z. B. bei größeren Datensätzen mit der Dask-Bibliothek):

Anerkennung an:

Einige Work-In-Progress-Referenzen (Stand 2017) zum Umgang mit großen daskDatenmengen:

weiji14
quelle
Vielen Dank für den Vergleich, in der Tat ist die Zip-Version viel schneller
MCMZL