Convertir un DataFrame pandas en un GeoDataFrame


42

Cela semble être une question assez simple, mais je ne vois pas comment convertir un pandas DataFrame en GeoDataFrame pour une jointure spatiale.

Voici un exemple de l'utilisation de mes données 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

En fait, ce cadre de données a été créé à partir d’un fichier CSV. Par conséquent, s’il est plus facile de lire le fichier CSV directement en tant que GeoDataFrame, c’est très bien aussi.


1
utiliser GeoPandas
gène

Réponses:


78

Convertissez d'abord le contenu (par exemple Lat, les Loncolonnes) du DataFrame en géométries Shapely appropriées , puis utilisez-les avec le DataFrame d'origine pour créer un GeoDataFrame.

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)

Résultat:

    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)

Comme les géométries sont souvent au format WKT, j'ai pensé inclure un exemple pour ce cas également:

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)

Merci encore! C'est beaucoup plus simple et fonctionne très vite - bien mieux que de parcourir chaque rangée du df à mon n = 500 000 :)
atkat12

6
Gosh, merci! Je vérifie cette réponse comme tous les 2 jours :)
Owen

1
vous penseriez que ce serait la première entrée dans la documentation!
Dominik

+1 pour le shapely.wkt. Il m'a fallu un certain temps pour comprendre cela!
StefanK

14

Une ligne! De plus, des indicateurs de performance pour les utilisateurs de Big Data.

Soit a pandas.DataFramequi a x longitude et y latitude comme suit:

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

Convertissons le pandas.DataFrameen un geopandas.GeoDataFramecomme suit:

Importations de bibliothèques et améliorations rapides :

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

Code + temps de référence sur un jeu de données de test que j'ai traîné:

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

L'utilisation pandas.applyest étonnamment lente, mais peut être mieux adaptée à d'autres flux de travail (par exemple, sur des jeux de données plus volumineux utilisant la bibliothèque de masques):

Crédits à:

Quelques références de Work-In-Progress (à partir de 2017) pour la gestion de grands daskensembles de données:


Merci pour la comparaison, en effet la version zip est bien plus rapide
MCMZL
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.