Skip to content

Commit a883ff0

Browse files
Add sample from David Lapp demonstrating the use of GeoPandas with
SDO_GEOMETRY.
1 parent d242d6f commit a883ff0

File tree

1 file changed

+187
-0
lines changed

1 file changed

+187
-0
lines changed

samples/SpatialToGeoPandas.py

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
#------------------------------------------------------------------------------
2+
# Copyright 2018, Oracle and/or its affiliates. All rights reserved.
3+
#------------------------------------------------------------------------------
4+
5+
#------------------------------------------------------------------------------
6+
# SpatialToGeoPandas.py
7+
# GeoPandas is a popular python library for working with geospatial data.
8+
# GeoPandas extends the Pandas data analysis library with geospatial support
9+
# using the Shapely library for geometry object support.
10+
#
11+
# See http://geopandas.org, https://pandas.pydata.org,
12+
# and https://github.com/Toblerity/Shapely.
13+
#
14+
# This example shows how to bring geometries from Oracle Spatial (SDO_GEOMETRY
15+
# data type) into GeoPandas and perform a simple spatial operation. While the
16+
# spatial operation we perform in Python could have been performed in the
17+
# Oracle database, this example targets use cases where Python with GeoPandas
18+
# is being used to combine and work with geospatial data from numerous
19+
# additional sources such as files and web services.
20+
#
21+
# This script requires cx_Oracle 5.3 and higher.
22+
#------------------------------------------------------------------------------
23+
24+
from __future__ import print_function
25+
26+
import SampleEnv
27+
import cx_Oracle
28+
from shapely.wkb import loads
29+
import geopandas as gpd
30+
31+
# create Oracle connection and cursor objects
32+
connection = cx_Oracle.Connection(SampleEnv.MAIN_CONNECT_STRING)
33+
cursor = connection.cursor()
34+
35+
# enable autocommit to avoid the additional round trip to the database to
36+
# perform a commit; this should not be used if multiple statements must be
37+
# executed for a single transaction
38+
connection.autocommit = True
39+
40+
# define output type handler to fetch LOBs, avoiding the second round trip to
41+
# the database to read the LOB contents
42+
def OutputTypeHandler(cursor, name, defaultType, size, precision, scale):
43+
if defaultType == cx_Oracle.BLOB:
44+
return cursor.var(cx_Oracle.LONG_BINARY, arraysize = cursor.arraysize)
45+
connection.outputtypehandler = OutputTypeHandler
46+
47+
# drop and create table
48+
print("Dropping and creating table...")
49+
cursor.execute("""
50+
begin
51+
execute immediate 'drop table TestStates';
52+
exception when others then
53+
if sqlcode <> -942 then
54+
raise;
55+
end if;
56+
end;""")
57+
cursor.execute("""
58+
create table TestStates (
59+
state VARCHAR2(30) not null,
60+
geometry SDO_GEOMETRY not null
61+
)""")
62+
63+
# acquire types used for creating SDO_GEOMETRY objects
64+
typeObj = connection.gettype("MDSYS.SDO_GEOMETRY")
65+
elementInfoTypeObj = connection.gettype("MDSYS.SDO_ELEM_INFO_ARRAY")
66+
ordinateTypeObj = connection.gettype("MDSYS.SDO_ORDINATE_ARRAY")
67+
68+
# define function for creating an SDO_GEOMETRY object
69+
def CreateGeometryObj(*ordinates):
70+
geometry = typeObj.newobject()
71+
geometry.SDO_GTYPE = 2003
72+
geometry.SDO_SRID = 8307
73+
geometry.SDO_ELEM_INFO = elementInfoTypeObj.newobject()
74+
geometry.SDO_ELEM_INFO.extend([1, 1003, 1])
75+
geometry.SDO_ORDINATES = ordinateTypeObj.newobject()
76+
geometry.SDO_ORDINATES.extend(ordinates)
77+
return geometry
78+
79+
# create SDO_GEOMETRY objects for three adjacent states in the USA
80+
geometryNevada = CreateGeometryObj(-114.052025, 37.103989, -114.049797,
81+
37.000423, -113.484375, 37, -112.898598, 37.000401,-112.539604,
82+
37.000683, -112, 37.000977, -111.412048, 37.001514, -111.133018,
83+
37.00079,-110.75, 37.003201, -110.5, 37.004265, -110.469505, 36.998001,
84+
-110, 36.997967, -109.044571,36.999088, -109.045143, 37.375,
85+
-109.042824, 37.484692, -109.040848, 37.881176, -109.041405,38.153027,
86+
-109.041107, 38.1647, -109.059402, 38.275501, -109.059296, 38.5,
87+
-109.058868, 38.719906,-109.051765, 39, -109.050095, 39.366699,
88+
-109.050697, 39.4977, -109.050499, 39.6605, -109.050156,40.222694,
89+
-109.047577, 40.653641, -109.0494, 41.000702, -109.2313, 41.002102,
90+
-109.534233,40.998184, -110, 40.997398, -110.047768, 40.997696, -110.5,
91+
40.994801, -111.045982, 40.998013,-111.045815, 41.251774, -111.045097,
92+
41.579899, -111.045944, 42.001633, -111.506493, 41.999588,-112.108742,
93+
41.997677, -112.16317, 41.996784, -112.172562, 41.996643, -112.192184,
94+
42.001244,-113, 41.998314, -113.875, 41.988091, -114.040871, 41.993805,
95+
-114.038803, 41.884899, -114.041306,41, -114.04586, 40.116997,
96+
-114.046295, 39.906101, -114.046898, 39.542801, -114.049026, 38.67741,
97+
-114.049339, 38.572968, -114.049095, 38.14864, -114.0476,
98+
37.80946,-114.05098, 37.746284, -114.051666, 37.604805, -114.052025,
99+
37.103989)
100+
geometryWyoming = CreateGeometryObj(-111.045815, 41.251774, -111.045982,
101+
40.998013, -110.5, 40.994801, -110.047768, 40.997696, -110, 40.997398,
102+
-109.534233, 40.998184, -109.2313, 41.002102, -109.0494, 41.000702,
103+
-108.525368, 40.999634, -107.917793, 41.002071, -107.317177, 41.002956,
104+
-106.857178, 41.002697, -106.455704, 41.002167, -106.320587, 40.999153,
105+
-106.189987, 40.997604, -105.729874, 40.996906, -105.276604, 40.998188,
106+
-104.942848, 40.998226, -104.625, 41.00145, -104.052742, 41.001423,
107+
-104.051781, 41.39333, -104.052032, 41.564301, -104.052185, 41.697983,
108+
-104.052109, 42.001736, -104.052277, 42.611626, -104.052643, 43.000614,
109+
-104.054337, 43.47784, -104.054298, 43.503101, -104.055, 43.8535,
110+
-104.054108, 44.141102, -104.054001, 44.180401, -104.055458, 44.570877,
111+
-104.057205, 44.997444, -104.664658, 44.998631, -105.037872, 45.000359,
112+
-105.088867, 45.000462, -105.912819, 45.000957, -105.927612, 44.99366,
113+
-106.024239, 44.993591, -106.263, 44.993801, -107.054871, 44.996384,
114+
-107.133545, 45.000141, -107.911095, 45.001343, -108.248672, 44.999504,
115+
-108.620628, 45.000328, -109.082314, 44.999664, -109.102745, 45.005955,
116+
-109.797951, 45.002247, -110.000771, 45.003502, -110.10936, 45.003967,
117+
-110.198761, 44.99625, -110.286026, 44.99691, -110.361946, 45.000656,
118+
-110.402176, 44.993874, -110.5, 44.992355, -110.704506, 44.99239,
119+
-110.784241, 45.003021, -111.05442, 45.001392, -111.054558, 44.666336,
120+
-111.048203, 44.474144, -111.046272, 43.983456, -111.044724, 43.501213,
121+
-111.043846, 43.3158, -111.043381, 43.02013, -111.042786, 42.719578,
122+
-111.045967, 42.513187, -111.045944, 42.001633, -111.045097, 41.579899,
123+
-111.045815, 41.251774)
124+
geometryColorado = CreateGeometryObj(-109.045143, 37.375, -109.044571,
125+
36.999088, -108.378571, 36.999516, -107.481133, 37, -107.420311, 37,
126+
-106.876701, 37.00013, -106.869209, 36.992416, -106.475639, 36.993748,
127+
-106.006058, 36.995327, -105.717834, 36.995823, -105.220055, 36.995144,
128+
-105.154488, 36.995239, -105.028671, 36.992702, -104.407616, 36.993446,
129+
-104.007324, 36.996216, -103.085617, 37.000244, -103.001709, 37.000084,
130+
-102.986488, 36.998505, -102.759384, 37, -102.69767, 36.995132,
131+
-102.041794, 36.993061, -102.041191, 37.389172, -102.04113, 37.644268,
132+
-102.041695, 37.738529, -102.043938, 38.262466, -102.044113, 38.268803,
133+
-102.04483, 38.615234, -102.044762, 38.697556, -102.046112, 39.047035,
134+
-102.046707, 39.133144, -102.049301, 39.568176, -102.049347, 39.574062,
135+
-102.051277, 40.00309, -102.051117, 40.34922, -102.051003, 40.440018,
136+
-102.050873, 40.697556, -102.050835, 40.749596, -102.051155, 41.002384,
137+
-102.620567, 41.002609, -102.652992, 41.002342, -103.382011, 41.00227,
138+
-103.574036, 41.001736, -104.052742, 41.001423, -104.625, 41.00145,
139+
-104.942848, 40.998226, -105.276604, 40.998188, -105.729874, 40.996906,
140+
-106.189987, 40.997604, -106.320587, 40.999153, -106.455704, 41.002167,
141+
-106.857178, 41.002697, -107.317177, 41.002956, -107.917793, 41.002071,
142+
-108.525368, 40.999634, -109.0494, 41.000702, -109.047577, 40.653641,
143+
-109.050156, 40.222694, -109.050499, 39.6605, -109.050697, 39.4977,
144+
-109.050095, 39.366699, -109.051765, 39, -109.058868, 38.719906,
145+
-109.059296, 38.5, -109.059402, 38.275501, -109.041107, 38.1647,
146+
-109.041405, 38.153027, -109.040848, 37.881176, -109.042824, 37.484692,
147+
-109.045143, 37.375)
148+
149+
# Insert rows for test states. If we were analyzing these geometries in Oracle
150+
# we would also add Spatial metadata and indexes. However in this example we
151+
# are only storing the geometries so that we load them back into Python, so we
152+
# will skip the metadata and indexes.
153+
print("Adding rows to table...")
154+
data = [
155+
('Nevada', geometryNevada),
156+
('Colorado', geometryColorado),
157+
('Wyoming', geometryWyoming)
158+
]
159+
cursor.executemany('insert into TestStates values (:state, :obj)', data)
160+
161+
# We now have test geometries in Oracle Spatial (SDO_GEOMETRY) and will next
162+
# bring them back into Python to analyze with GeoPandas. GeoPandas is able to
163+
# consume geometries in the Well Known Text (WKT) and Well Known Binary (WKB)
164+
# formats. Oracle database includes utility functions to return SDO_GEOMETRY as
165+
# both WKT and WKB. Therefore we use that utility function in the query below
166+
# to provide results in a format readily consumable by GeoPandas. These utility
167+
# functions were introduced in Oracle 10g. We use WKB here; however the same
168+
# process applies for WKT.
169+
cursor.execute("""
170+
SELECT state, sdo_util.to_wkbgeometry(geometry)
171+
FROM TestStates""")
172+
gdf = gpd.GeoDataFrame(cursor.fetchall(), columns = ['state', 'wkbgeometry'])
173+
174+
# create GeoSeries to replace the WKB geometry column
175+
gdf['geometry'] = gpd.GeoSeries(gdf['wkbgeometry'].apply(lambda x: loads(x)))
176+
del gdf['wkbgeometry']
177+
178+
# display the GeoDataFrame
179+
print()
180+
print(gdf)
181+
182+
# perform a basic GeoPandas operation (unary_union)
183+
# to combine the 3 adjacent states into 1 geometry
184+
print()
185+
print("GeoPandas combining the 3 geometries into a single geometry...")
186+
print(gdf.unary_union)
187+

0 commit comments

Comments
 (0)