74 votos

Conversión de Pandas DataFrame a GeoDataFrame

Parece una pregunta bastante sencilla, pero no consigo averiguar cómo convertir un DataFrame de Pandas en un GeoDataFrame para una unión espacial.

Este es un ejemplo de cómo se ven mis datos usando 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

De hecho, este marco de datos fue creado a partir de un CSV, así que si es más fácil leer el CSV directamente como un GeoDataFrame, también está bien.

131voto

Mark H Puntos 2378

Convertir el contenido del DataFrame (por ejemplo Lat y Lon columnas) en las correspondientes Shapely geometrías primero y luego usarlas 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)

Como las geometrías suelen venir en formato WKT, he pensado en incluir también un ejemplo para ese caso:

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)

53voto

Richard Watson Puntos 1863

Actualización 201912: La documentación oficial en https://geopandas.readthedocs.io/en/latest/gallery/create_geopandas_from_pandas.html lo hace de forma sucinta utilizando geopandas.points_from_xy así:

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, la elevación) si lo desea.


Método antiguo: Usando la forma

Unas cuantas líneas Y algunos consejos de rendimiento para la gente de big data.

Dada una pandas.DataFrame que tiene una longitud x y una latitud y 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 de la siguiente manera:

Importaciones de la biblioteca y aceleradores de forma :

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

Utilizando pandas.apply es sorprendentemente más lento, pero puede ser más adecuado para algunos otros flujos de trabajo (por ejemplo, en conjuntos de datos más grandes utilizando la biblioteca dask):

Créditos para:

Algunas referencias de Work-In-Progress (a partir de 2017) para manejar grandes dask conjuntos de datos:

0voto

Hellen Puntos 108

Aquí hay una función tomada de las internas de geopandas y ligeramente modificada para manejar un dataframe con una columna de geometría/polígono ya en formato wkt.

from geopandas import GeoDataFrame
import shapely

def df_to_geodf(df, geom_col="geom", crs=None, wkt=True):
  """
  Transforms a pandas DataFrame into a GeoDataFrame.
  The column 'geom_col' must be a geometry column in WKB representation.
  To be used to convert df based on pd.read_sql to gdf.
  Parameters
  ----------
  df : DataFrame
      pandas DataFrame with geometry column in WKB representation.
  geom_col : string, default 'geom'
      column name to convert to shapely geometries
  crs : pyproj.CRS, optional
      CRS to use for the returned GeoDataFrame. The value can be anything accepted
      by :meth:`pyproj.CRS.from_user_input() <pyproj.crs.CRS.from_user_input>`,
      such as an authority string (eg "EPSG:4326") or a WKT string.
      If not set, tries to determine CRS from the SRID associated with the
      first geometry in the database, and assigns that to all geometries.
  Returns
  -------
  GeoDataFrame
  """

  if geom_col not in df:
    raise ValueError("Query missing geometry column '{}'".format(geom_col))

  geoms = df[geom_col].dropna()

  if not geoms.empty:
    if wkt == True:
      load_geom = shapely.wkt.loads
    else:
      load_geom_bytes = shapely.wkb.loads
      """Load from Python 3 binary."""

      def load_geom_buffer(x):
        """Load from Python 2 binary."""
        return shapely.wkb.loads(str(x))

      def load_geom_text(x):
        """Load from binary encoded as text."""
        return shapely.wkb.loads(str(x), hex=True)

      if isinstance(geoms.iat[0], bytes):
        load_geom = load_geom_bytes
      else:
        load_geom = load_geom_text

    df[geom_col] = geoms = geoms.apply(load_geom)
    if crs is None:
      srid = shapely.geos.lgeos.GEOSGetSRID(geoms.iat[0]._geom)
      # if no defined SRID in geodatabase, returns SRID of 0
      if srid != 0:
        crs = "epsg:{}".format(srid)

  return GeoDataFrame(df, crs=crs, geometry=geom_col)

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X