Write GeoDataFrame into SQL Database

前端 未结 3 1808
盖世英雄少女心
盖世英雄少女心 2020-12-05 20:37

I hope that my question is not ridiculous since, surprisingly, this question has apparently not really been asked yet (to the best of my knowledge) on the popular websites.<

相关标签:
3条回答
  • 2020-12-05 21:15

    A version of Hamri Said's answer, but using a lambda, which in my opinion is a bit nicer because it is such a short function:

    # Imports
    from geoalchemy2 import Geometry, WKTElement
    from sqlalchemy import *
    
    geodataframe['geom'] = geodataframe['geom'].apply(lambda geom: WKTElement(geom.wkt, srid = <your_SRID>))
    
    db_url = 'postgresql://username:password@host:socket/database'
    engine = create_engine(db_url, echo=False)
    
    # Use 'dtype' to specify column's type
    # For the geom column, we will use GeoAlchemy's type 'Geometry'
    your_geodataframe.to_sql(table_name, engine, if_exists='append', index=False, 
                             dtype={'geom': Geometry('POINT', srid= <your_srid>)})
    
    0 讨论(0)
  • 2020-12-05 21:24

    As mentioned before, @Kartik's answer works only for a single call, for appending data it raises a DataError since the geom column then expects the geometry to have an SRID. You can use GeoAlchemy to handle all the cases:

    # Imports
    from geoalchemy2 import Geometry, WKTElement
    from sqlalchemy import *
    
    # Use GeoAlchemy's WKTElement to create a geom with SRID
    def create_wkt_element(geom):
        return WKTElement(geom.wkt, srid = <your_SRID>)
    
    geodataframe['geom'] = geodataframe['geom'].apply(create_wkt_element)
    
    db_url = 'postgresql://username:password@host:socket/database'
    engine = create_engine(db_url, echo=False)
    
    # Use 'dtype' to specify column's type
    # For the geom column, we will use GeoAlchemy's type 'Geometry'
    your_geodataframe.to_sql(table_name, engine, if_exists='append', index=False, 
                             dtype={'geom': Geometry('POINT', srid= <your_srid>)})
    
    0 讨论(0)
  • 2020-12-05 21:30

    So, I just implemented this for a PostGIS database, and I can paste my method here. For MySQL, you'll have to adapt the code.

    First step was to convert the geocoded columns into WKB hex string, because I use SQLAlchemy, with an engine based on pyscopg, and both of those packages do not understand geo-types natively. Next step is to write that data into a SQL DB, as usual (note that all geometry columns should be converted to text columns holding the WKB hex string), and finally change the type of the columns to Geometry by executing a query. Refer to the following pseudocode:

    # Imports
    import sqlalchemy as sal
    import geopandas as gpd
    
    # Function to generate WKB hex
    def wkb_hexer(line):
        return line.wkb_hex
    
    # Convert `'geom'` column in GeoDataFrame `gdf` to hex
        # Note that following this step, the GeoDataFrame is just a regular DataFrame
        # because it does not have a geometry column anymore. Also note that
        # it is assumed the `'geom'` column is correctly datatyped.
    gdf['geom'] = gdf['geom'].apply(wkb_hexer)
    
    # Create SQL connection engine
    engine = sal.create_engine('postgresql://username:password@host:socket/database')
    
    # Connect to database using a context manager
    with engine.connect() as conn, conn.begin():
        # Note use of regular Pandas `to_sql()` method.
        gdf.to_sql(table_name, con=conn, schema=schema_name,
                   if_exists='append', index=False)
        # Convert the `'geom'` column back to Geometry datatype, from text
        sql = """ALTER TABLE schema_name.table_name
                   ALTER COLUMN geom TYPE Geometry(LINESTRING, <SRID>)
                     USING ST_SetSRID(geom::Geometry, <SRID>)"""
        conn.execute(sql)
    
    0 讨论(0)
提交回复
热议问题