Thêm GeoPandas Dataframe vào bảng PostGIS?


14

Tôi có một Dataframe GeoPandas đơn giản:

nhập mô tả hình ảnh ở đây

Tôi muốn tải GeoDataframe này lên bảng PostGIS. Tôi đã thiết lập Cơ sở dữ liệu với tiện ích mở rộng PostGIS nhưng dường như không thể thêm Dataframe này dưới dạng bảng.

Tôi đã thử như sau:

engine = <>
meta = MetaData(engine)
eld_test = Table('eld_test', meta, Column('id', Integer, primary_key=True), Column('key_comb_drvr', Text), 
                 Column('geometry', Geometry('Point', srid=4326))) 
eld_test.create(engine) 
conn = engine.connect() 
conn.execute(eld_test.insert(), df.to_dict('records'))

Tôi đã thử các cách sau: engine = <> # tạo bảng meta = MetaData (engine) eld_test = Table ('eld_test', meta, Cột ('id', Integer, primary_key = True), Cột ('key_comb_drvr', Text) , Cột ('hình học', Hình học ('Điểm', srid = 4326))) eld_test.create (engine) # DBAPI's execemany với danh sách dicts Conn = engine.connect () Conn.execute (eld_test.insert (), df .to_dict ('records'))
thecornman

1
Chào mừng bạn đến với GIS SE, xin vui lòng đọc tour của chúng tôi ! Bạn có thể chỉnh sửa bài viết của bạn để bao gồm mã của bạn được đăng trong các ý kiến?
GISKid

Câu trả lời:


27

Sử dụng phương thức to_sql của Panda và SQLAlchemy, bạn có thể lưu trữ một khung dữ liệu trong Postgres. Và vì bạn đang lưu trữ Geodataframe, GeoAlchemy sẽ xử lý cột geom cho bạn. Đây là một mẫu mã:

# Imports
from geoalchemy2 import Geometry, WKTElement
from sqlalchemy import *
import pandas as pd
import geopandas as gpd

# Creating SQLAlchemy's engine to use
engine = create_engine('postgresql://username:password@host:socket/database')


geodataframe = gpd.GeoDataFrame(pd.DataFrame.from_csv('<your dataframe source>'))
#... [do something with the geodataframe]

geodataframe['geom'] = geodataframe['geometry'].apply(lambda x: WKTElement(x.wkt, srid=<your_SRID>)

#drop the geometry column as it is now duplicative
geodataframe.drop('geometry', 1, inplace=True)

# Use 'dtype' to specify column's type
# For the geom column, we will use GeoAlchemy's type 'Geometry'
geodataframe.to_sql(table_name, engine, if_exists='append', index=False, 
                         dtype={'geom': Geometry('POINT', srid= <your_srid>)})

Đáng lưu ý rằng tham số 'if_exists' cho phép bạn xử lý cách khung dữ liệu sẽ được thêm vào bảng postgres của bạn:

    if_exists = replace: If table exists, drop it, recreate it, and insert data.
    if_exists = fail: If table exists, do nothing.
    if_exists = append: If table exists, insert data. Create if does not exist.

4

Tôi cũng đã có cùng một câu hỏi mà bạn đã hỏi và đã dành nhiều, rất nhiều ngày cho nó (hơn cả tôi quan tâm để thừa nhận) tìm kiếm một giải pháp. Giả sử bảng postgreSQL sau với phần mở rộng 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)

đây là những gì tôi cuối cùng đã làm việc:

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

Tôi không thể nói nếu logic kết nối cơ sở dữ liệu của tôi là tốt nhất vì về cơ bản tôi đã sao chép nó từ một liên kết khác và rất vui khi tôi có thể tự động hóa thành công (hoặc phản ánh) bảng hiện có của mình với định nghĩa hình học được nhận dạng. Tôi đã viết python sang mã không gian sql chỉ trong một vài tháng, vì vậy tôi biết có nhiều điều để tìm hiểu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.