Nuestros mejores investigadores han agotado sus provisiones de café, por su búsqueda a tiempo completo por la solución, hasta que América halló el arreglo en Bitbucket y hoy la comparte aquí.
Solución:
Convierta el contenido del DataFrame (p. ej. Lat
y Lon
columnas) en geometrías Shapely apropiadas primero y luego úselas junto con el DataFrame original para crear 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)
gdf = GeoDataFrame(df, crs="EPSG:4326", geometry=geometry)
Resultado:
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)
Dado que las geometrías a menudo vienen en formato WKT, pensé en incluir un ejemplo para ese caso también:
import geopandas as gpd
import shapely.wkt
geometry = df['wktcolumn'].map(shapely.wkt.loads)
df = df.drop('wktcolumn', axis=1)
gdf = gpd.GeoDataFrame(df, crs="EPSG:4326", geometry=geometry)
Actualización 201912: la documentación oficial en https://geopandas.readthedocs.io/en/latest/gallery/create_geopandas_from_pandas.html lo hace de manera sucinta usando geopandas.points_from_xy
al igual que:
gdf = geopandas.GeoDataFrame(
df, geometry=geopandas.points_from_xy(x=df.Longitude, y=df.Latitude)
)
También puede establecer un crs
o z
(por ejemplo, elevación) valor si lo desea.
Método antiguo: usar bien formado
¡De una sola línea! Además de algunos indicadores de rendimiento para la gente de big data.
Dado un pandas.DataFrame
que tiene x Longitud y y Latitud así:
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
Convirtamos el pandas.DataFrame
en un geopandas.GeoDataFrame
como sigue:
Importaciones de bibliotecas y aceleraciones bien formadas:
import geopandas as gpd
import shapely
shapely.speedups.enable() # enabled by default from version 1.6.0
Código + tiempos de referencia en un conjunto de datos de prueba que tengo por ahí:
#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))
Usando pandas.apply
es sorprendentemente más lento, pero puede adaptarse mejor a otros flujos de trabajo (por ejemplo, en conjuntos de datos más grandes que usan la biblioteca dask):
Créditos para:
- ¿Hacer un archivo de forma a partir del marco de datos de Pandas? (para el método de aplicación de pandas)
- Acelere el punto de fila en el polígono con Geopandas (para la sugerencia de aceleración)
Algunas referencias de Work-In-Progress (a partir de 2017) para manejar grandes dask
conjuntos de datos:
- http://matthewrocklin.com/blog/work/2017/09/21/accelerating-geopandas-1
- https://github.com/geopandas/geopandas/issues/461
- https://github.com/mrocklin/dask-geopandas
Reseñas y valoraciones
Recuerda que te permitimos decir si te ayudó.