También he tenido la misma pregunta que me has hecho y he pasado muchos, muchos días en ella (más de lo que me gustaría admitir) buscando una solución. Suponiendo la siguiente tabla postgreSQL con la extensión postGIS,
postgres=> \d cldmatchup.geo_points;
Table "cldmatchup.geo_points"
Column | Type | Modifiers
-----------+----------------------+------------------------------------------------------------------------
gridid | bigint | not null default nextval('cldmatchup.geo_points_gridid_seq'::regclass)
lat | real |
lon | real |
the_point | geography(Point,4326) |
Indexes:
"geo_points_pkey" PRIMARY KEY, btree (gridid)
Esto es lo que finalmente conseguí trabajar:
import geopandas as gpd
from geoalchemy2 import Geography, Geometry
from sqlalchemy import create_engine, MetaData, Table
from sqlalchemy.orm import sessionmaker
from shapely.geometry import Point
from psycopg2.extensions import adapt, register_adapter, AsIs
# From http://initd.org/psycopg/docs/advanced.html#adapting-new-types but
# modified to accomodate postGIS point type rather than a postgreSQL
# point type format
def adapt_point(point):
from psycopg2.extensions import adapt, AsIs
x = adapt(point.x).getquoted()
y = adapt(point.y).getquoted()
return AsIs("'POINT (%s %s)'" % (x, y))
register_adapter(Point, adapt_point)
engine = create_engine('postgresql://<yourUserName>:postgres@localhost:5432/postgres', echo=False)
Session = sessionmaker(bind=engine)
session = Session()
meta = MetaData(engine, schema='cldmatchup')
# Create reference to pre-existing "geo_points" table in schema "cldmatchup"
geoPoints = Table('geo_points', meta, autoload=True, schema='cldmatchup', autoload_with=engine)
df = gpd.GeoDataFrame({'lat':[45.15, 35., 57.], 'lon':[-35, -150, -90.]})
# Create a shapely.geometry point
the_point = [Point(xy) for xy in zip(df.lon, df.lat)]
# Create a GeoDataFrame specifying 'the_point' as the column with the
# geometry data
crs = {'init': 'epsg:4326'}
geo_df = gpd.GeoDataFrame(df.copy(), crs=crs, geometry=the_point)
# Rename the geometry column to match the database table's column name.
# From https://media.readthedocs.org/pdf/geopandas/latest/geopandas.pdf,
# Section 1.2.2 p 7
geo_df = geo_df.rename(columns{'geometry':'the_point'}).set_geometry('the_point')
# Write to sql table 'geo_points'
geo_df.to_sql(geoPoints.name, engine, if_exists='append', schema='cldmatchup', index=False)
session.close()
No puedo decir si la lógica de conexión de mi base de datos es la mejor, ya que básicamente copié eso de otro enlace y me alegré de haber podido automatizar (o reflejar) con éxito mi tabla existente con la definición de geometría reconocida. He estado escribiendo código espacial de Python a SQL durante solo unos meses, así que sé que hay mucho que aprender.