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