Mineração de Dados Geoespaciais - Anexo II

Fernando Ferraz Ribeiro

Beth Leite Soares

O objetivo deste notebook exportar dados de um shapefile e dados baixados do open street maps para tabelas em um banco de dados georeferenciado (Postgis)

Testando o ambiente de trabalho (conda environment)

Mostrando o caminho que o servidor Jupyter carrega interpretador o Python (python.exe) e carregas o anbiente (\envs)

In [1]:
import os
import sys
print(sys.executable)
pathFix = sys.prefix
print(pathFix)
C:\Users\ffrib\AppData\Local\conda\conda\envs\Geodata_2018_12_08\python.exe
C:\Users\ffrib\AppData\Local\conda\conda\envs\Geodata_2018_12_08

Lidando com erros do ambiente (WINDOWS ONLY)

Algumas bibliotecas importadas apresentam um erro apendas na plataforma Windows.

Caso esteja rodando no windows e tenha problemas com o sistema de coordenadas de referĂȘncia (crs), rode a linha de comando abaixo:

In [2]:
pathFix = pathFix .replace('\\', '/')
print(pathFix)
os.environ["PROJ_LIB"] =   pathFix + "/Library/share"
C:/Users/ffrib/AppData/Local/conda/conda/envs/Geodata_2018_12_08

mais informaçÔes no Post sobre o Erro

Importando Bibliotecas

In [3]:
# Biblioteca basica de programação científica em python
import numpy as np
# biblioteca de anĂĄlise de dados
import pandas as pd
# biblioteca de grĂĄficos
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.colors as colors
# Bibliotecas geopandas
import geopandas as gpd
# biblioteca de redes complexas
import networkx as nx
# biblioteca para acessar dados do Open sreet maps
import osmnx as ox
# bibliotecas de leitura e escrita em banco de dados
from geoalchemy2 import Geometry, WKTElement
# bibliotecas de leitura e escrita em banco de dados geoespaciais
from sqlalchemy import *
In [4]:
%matplotlib inline
ox.config(use_cache=True, log_console=True)
ox.__version__
Out[4]:
'0.8.2'

Criando coordenadas de recorte

In [5]:
# coordenada inicial x
xSC = 555000
# variação da coordenada x
deltaX = 2000
# coordenada inicial y
ySC = 8570000
# variação da coordenada y
deltaY = 2000

Limites da importaçâo

In [6]:
from shapely.geometry import Polygon

recorte = gpd.GeoSeries([ Polygon([(xSC,ySC), (xSC + deltaX , ySC), (xSC + deltaX, ySC + deltaY ), (xSC, ySC + deltaY )]) ])

A geometria criada pela linha de comando acima, embora tenha as corrdenadas relativas ao sistema de projeção Sigras 2000, nĂŁo tem nenhuma informação georreferenciada. É preciso informar qual o sistema de coordenadas de referĂȘncia utilizado ( coordenates reference sistem - crs). O Bloco de cĂłdigo abaxo informa que as coordenadas do recorte devem ser tratadas com o sistema Sigras 2000. com unidades em metro.

In [7]:
# colocando em coordenaadas SIRGAS 2000
recorte.crs = {'proj': 'utm', 'zone': 24, 'south': True, 'ellps': 'aust_SA', 'units': 'm', 'no_defs': True}
#recorte.crs ={'init': 'epsg:4674', 'units': 'm', 'no_defs': True}

Carregando shapes

In [8]:
# importando Shape dos bairros - polĂ­gonos
bairros = gpd.read_file('../shapefiles/BaseSSA/Limites/bairros_fim.shp', bbox = recorte )

# importando Shape das edificaçÔs - polilinhas
edf = gpd.read_file('../shapefiles/BaseSSA/edificacoes_polyline.shp', bbox = recorte)

# importando shape de pontos
edf_pt = gpd.read_file('../shapefiles/BaseSSA/edificacoes_point.shp', bbox = recorte)

Mostrando os dados dos shapes

Dados do shape bairros

In [9]:
bairros.head()
Out[9]:
OBJECTID BR_ BR_ID NM_BAIRROS Shape_Leng Shape_Area geometry
0 89 2 1 Lobato 10290.734146 1.508163e+06 POLYGON ((556643.6323074758 8573040.904571733,...
1 91 2 1 Massaranduba 5027.152427 5.301521e+05 POLYGON ((555124.2668471506 8570956.484697679,...
2 92 2 1 Santa Luzia 5579.648112 3.957189e+05 POLYGON ((556131.141931782 8571133.633667247, ...
3 98 2 1 Alto do Cabrito 5031.429303 1.112943e+06 POLYGON ((557394.0547874847 8572993.633136973,...
4 99 2 1 Capelinha 3337.251376 4.201418e+05 POLYGON ((556500.9559292701 8570974.556498181,...

Dados do shape edificacoes

In [10]:
edf.head()
Out[10]:
ID geometry
0 357236 LINESTRING (555000.0316226622 8570905.59166144...
1 357238 LINESTRING (554999.0173801129 8570926.86740669...
2 357239 LINESTRING (555000.4686540046 8570930.90659893...
3 357240 LINESTRING (555002.9094328225 8570934.45588914...
4 357241 LINESTRING (555009.4978864561 8570930.67664492...
In [11]:
edf_pt.head()
Out[11]:
ID geometry
0 367175 (POINT (556360.5184374301 8570865.76962509))
1 367176 (POINT (556360.5184374301 8570865.76962509))
2 367177 (POINT (556360.5184374301 8570865.76962509))
3 367178 (POINT (556497.9771634268 8571237.37531103))
4 367179 (POINT (556360.5184374301 8570865.76962509))

Lendo Arquivos do banco de dados espaciais online Open Street maps

Baixando arquivos por coordenadas limite

O open street maps trabalha com coordenadas WGS84, definidas pelo cĂłdigo epsg 4326. O sistema WGS84 utiliza coordenadas em graus de latitude e longitude.

In [12]:
recorte.bounds
Out[12]:
minx miny maxx maxy
0 555000.0 8570000.0 557000.0 8572000.0

Para utilizar a mesma geometria limite da utilizada para a importação do Shapefile, Ă© preciso converter o sistema de coordenadas de referĂȘncia de Sigras 2000 para WGS84.

In [13]:
recorte_LL = recorte.to_crs({'init': 'epsg:4326'})
recorte_LL.bounds
Out[13]:
minx miny maxx maxy
0 -38.49299 -12.934936 -38.474516 -12.916815

O elemento de Ă­ndice 0 da coluna geometry Ă© um polĂ­gono da biblioteca shapely.

In [14]:
 type(recorte_LL.geometry[0])
Out[14]:
shapely.geometry.polygon.Polygon

segundo a documentação do comando ox.graph_from_polygon ele recebe como priméiro parùmetro um polígono ou multi-polígono da biblioteca citada.

O download do multi-grafo depende da conexĂŁo com a internet

In [15]:
gLatLon =  ox.graph_from_polygon(
                                   recorte_LL.geometry[0]
                                 , network_type='all_private'
                                 , truncate_by_edge= True
                                 , retain_all = True
                            )
In [16]:
gLatLon
Out[16]:
<networkx.classes.multidigraph.MultiDiGraph at 0x1dc1473cb70>
In [17]:
ox.plot_graph(ox.project_graph(gLatLon))
Out[17]:
(<Figure size 449.029x432 with 1 Axes>,
 <matplotlib.axes._subplots.AxesSubplot at 0x1dc14ea3c50>)

Juntando O arquivo OSM com o Arquivo SHP

Trasnformando de Grafo OSM para geopandas Data frame

In [18]:
osm_pontos, osm_linhas = ox.save_load.graph_to_gdfs(gLatLon)
In [19]:
osm_linhas.head()
Out[19]:
bridge geometry highway key lanes length maxspeed name oneway osmid service u v
0 NaN LINESTRING (-38.4817005 -12.9226106, -38.48173... footway 0 NaN 5.818 NaN NaN False 431452585 NaN 592377792 4306484891
1 NaN LINESTRING (-38.4817005 -12.9226106, -38.48143... primary 0 2 293.516 60 Avenida AfrĂąnio Peixoto True 258852462 NaN 592377792 3944737722
2 NaN LINESTRING (-38.4806693 -12.9168449, -38.48061... secondary_link 0 NaN 6.314 NaN NaN True 86577754 NaN 592378346 4306607916
3 NaN LINESTRING (-38.4806693 -12.9168449, -38.48063... primary 0 2 69.680 60 Avenida AfrĂąnio Peixoto True 406250331 NaN 592378346 592378351
4 NaN LINESTRING (-38.4806036 -12.9174681, -38.48123... residential 0 NaN 233.994 NaN NaN False 88627556 NaN 592378351 1029167862

Sistemas de coordenadas

trasnformando para o sistema Sigras 2000

In [20]:
# Mudando o sistema de coordenadas de referĂȘncia

# Para o Shape de Pontos
osm_pontos.to_crs(bairros.crs, inplace = True)
# Para o Shape de Bairros
osm_linhas.to_crs(bairros.crs, inplace = True)

Odenando as colunas do shape das linhas

In [21]:
# Ordenando as colunas das linhas para que a coluna de geometria fique por Ășltimo
osm_linhas_cols = osm_linhas.columns.tolist()
osm_linhas_cols = [x for x in osm_linhas_cols if x != 'geometry']
osm_linhas_cols.append('geometry')
osm_linhas = osm_linhas[osm_linhas_cols]
In [22]:
osm_linhas.head()
Out[22]:
bridge highway key lanes length maxspeed name oneway osmid service u v geometry
0 NaN footway 0 NaN 5.818 NaN NaN False 431452585 NaN 592377792 4306484891 LINESTRING (556223.3656601022 8571360.65885263...
1 NaN primary 0 2 293.516 60 Avenida AfrĂąnio Peixoto True 258852462 NaN 592377792 3944737722 LINESTRING (556223.3656601022 8571360.65885263...
2 NaN secondary_link 0 NaN 6.314 NaN NaN True 86577754 NaN 592378346 4306607916 LINESTRING (556336.5217465418 8571998.06138254...
3 NaN primary 0 2 69.680 60 Avenida AfrĂąnio Peixoto True 406250331 NaN 592378346 592378351 LINESTRING (556336.5217465418 8571998.06138254...
4 NaN residential 0 NaN 233.994 NaN NaN False 88627556 NaN 592378351 1029167862 LINESTRING (556343.5093335714 8571929.12723277...
In [23]:
osm_pontos.head()
Out[23]:
highway osmid x y geometry
592377792 NaN 592377792 -38.4817 -12.9226 POINT (556223.3656601022 8571360.658852631)
592377803 NaN 592377803 -38.4805 -12.9169 POINT (556350.339344732 8571996.562528457)
592378346 NaN 592378346 -38.4807 -12.9168 POINT (556336.5217465418 8571998.061382545)
592378351 NaN 592378351 -38.4806 -12.9175 POINT (556343.5093335714 8571929.127232777)
592378362 NaN 592378362 -38.4815 -12.9222 POINT (556243.6960290928 8571404.168260001)

Plotando os Data Frames

In [24]:
fig2, layers2 = plt.subplots(figsize=(10,10)
                            #,dpi=30
                           )

recorte.plot(ax = layers2, color = 'blue', alpha = 1)
# Plotando os bairros
# Limites preto
# alpha - transparĂȘncia
# layers - quadro o qual poderĂĄ ser alterado os valores de xmin, xmax, tĂ­tulo e etc


bairros.plot(ax= layers2, color='yellowgreen', edgecolor='black', linestyle="--", lw= 1.5, alpha=1) 

# Plotando as edificaçÔes com a cor vermelha
edf.plot(ax= layers2, color='darkred', lw= 0.7)

try:
    edf_pt.plot(ax= layers2, color='orange', lw= 0.7, )
except:
    pass

# importados do OSM
osm_linhas.plot(ax= layers2, color='teal', lw= 0.8, )
osm_pontos.plot(ax= layers2, color='indigo', lw= 0.4, )

# titulo da figura
fig2.suptitle('Imagem Teste', fontsize=16)

# limites do grĂĄfico
layers2.set_xlim(xSC, xSC + deltaX )
layers2.set_ylim(ySC,  ySC + deltaY )
Out[24]:
(8570000, 8572000)

Gravando no banco de dados

In [25]:
engine = create_engine('postgresql://postgres:1234@localhost:5432/sdb_arqb30')
In [26]:
bairros['geom'] = bairros['geometry'].apply(lambda x: WKTElement(x.wkt, srid= 31984))
In [27]:
bairros.drop('geometry', 1, inplace=True)
In [28]:
bairros.to_sql('bairrosSSAPoly', engine, if_exists='append', index=False, 
                         dtype={'geom': Geometry('Polygon', srid= 31984)})
In [29]:
osm_linhas['geom'] = osm_linhas['geometry'].apply(lambda x: WKTElement(x.wkt, srid= 31984))
osm_linhas.drop('geometry', 1, inplace=True)
In [30]:
osm_linhas.to_sql('osm_linhas', engine, if_exists='append', index=False, 
                         dtype={'geom': Geometry('LINESTRING ', srid= 31984)})