📖 Glossário - Análise Geoespacial
A
Atributo (Feature Attribute): Informação descritiva associada a uma feição geográfica (nome, população, área, etc).
B
Bounding Box: Retângulo que delimita a extensão mínima de um conjunto de geometrias.
Buffer: Operação que cria área ao redor de geometria com distância específica.
C
Centroide: Ponto central de uma geometria.
CRS (Coordinate Reference System): Sistema de coordenadas que define como posições geográficas são representadas.
CSV (Comma-Separated Values): Formato de arquivo tabular com valores separados por vírgula.
D
DataFrame: Estrutura de dados tabular do pandas com linhas e colunas.
Dissolve: Operação que combina geometrias adjacentes em uma única.
E
EPSG: Código numérico que identifica sistemas de coordenadas (ex: EPSG:4326 = WGS84).
Extent: Limites geográficos (min/max X e Y) de uma área.
F
Feature (Feição): Entidade geográfica com geometria e atributos (ponto, linha ou polígono).
Feature Collection: Coleção de múltiplas feições GeoJSON.
G
Geocodificação: Processo de converter endereços em coordenadas.
GeoDataFrame: DataFrame do GeoPandas com coluna de geometrias.
Geografia: Ciência que estuda a superfície terrestre e distribuição espacial de fenômenos.
GeoJSON: Formato JSON para codificar estruturas de dados geográficos.
GeoPandas: Biblioteca Python para manipular dados geoespaciais.
Geometria: Representação matemática de forma espacial (ponto, linha, polígono).
GIS (Geographic Information System): Sistema para capturar, armazenar, analisar e gerenciar dados espaciais.
I
Interseção (Intersection): Operação que retorna geometria comum entre duas outras.
L
Latitude: Coordenada que indica posição norte-sul (0° no Equador, -90° a +90°).
Layer (Camada): Conjunto de dados geográficos relacionados.
LineString: Geometria GeoJSON representando linha conectando pontos.
Longitude: Coordenada que indica posição leste-oeste (0° em Greenwich, -180° a +180°).
M
Mapa: Representação visual de informações geográficas.
Mapa de calor (Heatmap): Visualização que usa cor para mostrar densidade/intensidade.
Marker (Marcador): Ícone que indica localização em mapa.
Mercator: Projeção cilíndrica comum em mapas web.
MultiPoint/MultiLineString/MultiPolygon: Geometrias compostas por múltiplas partes.
O
Overlay: Operação que combina duas camadas espaciais.
P
Plotly: Biblioteca Python para visualizações interativas.
Point (Ponto): Geometria mais simples representando localização (X, Y).
Polygon (Polígono): Geometria fechada representando área.
Projeção: Transformação de coordenadas 3D (Terra) para 2D (mapa).
R
Raster: Dados espaciais em formato de grade de pixels (imagens, elevação).
Reprojetar: Converter dados de um CRS para outro.
S
Shapefile: Formato popular de arquivo para dados vetoriais GIS (.shp, .shx, .dbf).
SIG (Sistema de Informação Geográfica): Termo em português para GIS.
Spatial Join: Operação que une atributos baseado em relação espacial.
T
Tiles (Ladrilhos): Pequenas imagens que compõem mapa web em diferentes zooms.
Topology (Topologia): Relações espaciais entre geometrias (adjacência, interseção, etc).
U
Union: Operação que combina geometrias em uma única.
V
Vetor: Dados geográficos representados por pontos, linhas e polígonos.
Visualização: Representação gráfica de dados para facilitar compreensão.
W
WGS84 (World Geodetic System 1984): Sistema de coordenadas geográficas padrão (EPSG:4326).
Z
Zoom: Nível de detalhe de visualização em mapa (maior número = mais próximo).
Exemplos Práticos
import geopandas as gpd
from shapely.geometry import Point, Polygon
# Criar GeoDataFrame de pontos
dados = {
'nome': ['Ingleses', 'Lagoa', 'Centro'],
'geometry': [
Point(-48.4, -27.4),
Point(-48.5, -27.6),
Point(-48.55, -27.58)
]
}
gdf = gpd.GeoDataFrame(dados, crs="EPSG:4326")
# Criar buffer de 1 km
gdf_buffer = gdf.to_crs("EPSG:31982") # Projetar para metros
gdf_buffer['geometry'] = gdf_buffer.buffer(1000)
# Ler shapefile
praias = gpd.read_file("praias.shp")
# Interseção espacial
praias_proximas = gpd.sjoin(praias, gdf_buffer, how='inner')
# Salvar como GeoJSON
praias_proximas.to_file("praias_proximas.geojson", driver='GeoJSON')
# Plotar
praias.plot(figsize=(10, 10), color='blue')
Sistemas de Coordenadas Comuns
| EPSG | Nome | Uso |
|---|---|---|
| 4326 | WGS84 | GPS, Google Maps, coordenadas geográficas |
| 3857 | Web Mercator | Mapas web (Google, OpenStreetMap) |
| 31982 | SIRGAS 2000 / UTM 22S | Brasil - SC, RS (coordenadas métricas) |
| 4674 | SIRGAS 2000 | Brasil - coordenadas geográficas |
💡 Dica: Use sempre gdf.crs para verificar o sistema de coordenadas do seu GeoDataFrame!
🗺️ GeoJSON - Dados Geográficos Básicos
O que é GeoJSON?
GeoJSON = formato de arquivo para armazenar dados geográficos em JSON.
Por que GeoJSON é importante?
Excel/CSV GeoJSON
├─ Dados tabulares ├─ Dados + Geografia
├─ Sem localização ├─ Coordenadas incluídas
└─ Sem mapas └─ Pronto para mapear
Usado em: Leaflet, Folium, QGIS, ArcGIS Online, Google Maps
📍 Coordenadas Geográficas
Antes de GeoJSON, você precisa entender coordenadas!
Latitude e Longitude
Latitude (Y) → Norte/Sul → -90° a +90°
Longitude (X) → Leste/Oeste → -180° a +180°
Brasil:
├─ Latitude: -33° a +5° (negativo = Sul)
└─ Longitude: -73° a -34° (negativo = Oeste)
Santa Catarina (exemplo):
├─ Florianópolis: -27.5969°, -48.5495°
├─ Praia dos Ingleses: -27.4374°, -48.3923°
└─ Laguna: -28.4833°, -48.7833°
Formato padrão: [longitude, latitude] ⚠️ Longitude vem PRIMEIRO!
📐 Tipos de Geometria
1. Point (Ponto)
Um único local.
{
"type": "Point",
"coordinates": [-48.5495, -27.5969]
}
Uso: Estação de coleta, localização de espécie
2. LineString (Linha)
Sequência de pontos conectados.
{
"type": "LineString",
"coordinates": [
[-48.5495, -27.5969],
[-48.5500, -27.6000],
[-48.5505, -27.6030]
]
}
Uso: Transecto, rota de barco, corrente marinha
3. Polygon (Polígono)
Área fechada.
{
"type": "Polygon",
"coordinates": [
[
[-48.5495, -27.5969],
[-48.5500, -27.5969],
[-48.5500, -27.6000],
[-48.5495, -27.6000],
[-48.5495, -27.5969]
]
]
}
⚠️ Primeiro e último ponto devem ser iguais!
Uso: Área de proteção, zona de coleta, habitat de espécie
🎯 Estrutura Completa de GeoJSON
Feature (Um objeto geográfico)
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-48.5495, -27.5969]
},
"properties": {
"nome": "Praia dos Ingleses",
"especie": "Ulva lactuca",
"profundidade_m": 5.2,
"temperatura_c": 22.5,
"data_coleta": "2025-01-06"
}
}
Partes:
- geometry: Localização geográfica
- properties: Dados descritivos (qualquer coisa!)
FeatureCollection (Múltiplos objetos)
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-48.5495, -27.5969]
},
"properties": {
"id": 1,
"especie": "Ulva lactuca",
"profundidade_m": 5.2
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-48.3923, -27.4374]
},
"properties": {
"id": 2,
"especie": "Gracilaria",
"profundidade_m": 7.8
}
}
]
}
🐍 Criar GeoJSON com Python
Instalar Bibliotecas
pip install geojson
Exemplo 1: Criar Ponto Simples
import json
# Criar Feature (ponto)
ponto_coleta = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-48.5495, -27.5969] # [lon, lat]
},
"properties": {
"nome": "Estação 1 - Praia dos Ingleses",
"especie": "Ulva lactuca",
"profundidade_m": 5.2,
"temperatura_c": 22.5,
"salinidade_psu": 35.0
}
}
# Salvar em arquivo
with open("ponto_coleta.geojson", "w", encoding="utf-8") as f:
json.dump(ponto_coleta, f, indent=2, ensure_ascii=False)
print("✅ GeoJSON criado: ponto_coleta.geojson")
Exemplo 2: Múltiplas Estações de Coleta
import json
# Dados de coleta (exemplo LAFIC)
coletas = [
{"nome": "Ingleses - Norte", "lon": -48.3923, "lat": -27.4374,
"especie": "Ulva lactuca", "prof": 5.2, "temp": 22.5},
{"nome": "Ingleses - Sul", "lon": -48.3950, "lat": -27.4450,
"especie": "Gracilaria", "prof": 7.8, "temp": 23.1},
{"nome": "Barra da Lagoa", "lon": -48.4200, "lat": -27.5750,
"especie": "Sargassum", "prof": 3.1, "temp": 22.8},
{"nome": "Laguna", "lon": -48.7833, "lat": -28.4833,
"especie": "Laminaria", "prof": 10.5, "temp": 21.2}
]
# Criar FeatureCollection
features = []
for i, coleta in enumerate(coletas, start=1):
feature = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [coleta["lon"], coleta["lat"]]
},
"properties": {
"id": i,
"nome": coleta["nome"],
"especie": coleta["especie"],
"profundidade_m": coleta["prof"],
"temperatura_c": coleta["temp"]
}
}
features.append(feature)
geojson_collection = {
"type": "FeatureCollection",
"features": features
}
# Salvar
with open("coletas_LAFIC.geojson", "w", encoding="utf-8") as f:
json.dump(geojson_collection, f, indent=2, ensure_ascii=False)
print(f"✅ GeoJSON criado com {len(features)} estações")
Exemplo 3: Criar Polígono (Área de Estudo)
import json
# Área de proteção marinha (exemplo)
area_protecao = {
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [[
[-48.5495, -27.5969], # Ponto 1
[-48.5400, -27.5969], # Ponto 2
[-48.5400, -27.6100], # Ponto 3
[-48.5495, -27.6100], # Ponto 4
[-48.5495, -27.5969] # Fecha (igual ao primeiro)
]]
},
"properties": {
"nome": "Área de Proteção Marinha - Ingleses",
"tipo": "Zona de coleta proibida",
"area_km2": 12.5,
"criacao": "2020-01-01"
}
}
# Salvar
with open("area_protecao.geojson", "w", encoding="utf-8") as f:
json.dump(area_protecao, f, indent=2, ensure_ascii=False)
print("✅ Área de proteção criada")
📊 Ler GeoJSON
Exemplo: Carregar e Processar
import json
# Carregar arquivo
with open("coletas_LAFIC.geojson", "r", encoding="utf-8") as f:
dados = json.load(f)
# Acessar features
print(f"Total de pontos: {len(dados['features'])}")
# Iterar sobre features
for feature in dados["features"]:
props = feature["properties"]
coords = feature["geometry"]["coordinates"]
print(f"\n📍 {props['nome']}")
print(f" Espécie: {props['especie']}")
print(f" Localização: {coords[1]:.4f}, {coords[0]:.4f}")
print(f" Profundidade: {props['profundidade_m']}m")
# Filtrar por espécie
ulvas = [f for f in dados["features"]
if f["properties"]["especie"] == "Ulva lactuca"]
print(f"\n🌿 Encontradas {len(ulvas)} amostras de Ulva lactuca")
🌐 Validar GeoJSON Online
Antes de usar em mapas, valide seu GeoJSON:
Ferramentas: 1. geojson.io - http://geojson.io - Cole seu GeoJSON - Visualize no mapa - Edite geometrias
- GeoJSONLint - https://geojsonlint.com
- Valida sintaxe
- Mostra erros
🎯 Exemplo Prático: Sistema de Cadastro
Crie arquivo cadastro_coletas.py:
import json
from datetime import datetime
def criar_ponto_coleta(nome, lon, lat, especie, profundidade, temperatura):
"""Cria um Feature GeoJSON para coleta"""
return {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [lon, lat]
},
"properties": {
"nome": nome,
"especie": especie,
"profundidade_m": profundidade,
"temperatura_c": temperatura,
"data_cadastro": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
}
def adicionar_coleta(arquivo, nova_coleta):
"""Adiciona uma coleta ao GeoJSON existente"""
try:
# Tentar carregar arquivo existente
with open(arquivo, "r", encoding="utf-8") as f:
dados = json.load(f)
except FileNotFoundError:
# Criar novo se não existe
dados = {
"type": "FeatureCollection",
"features": []
}
# Adicionar nova coleta
dados["features"].append(nova_coleta)
# Salvar
with open(arquivo, "w", encoding="utf-8") as f:
json.dump(dados, f, indent=2, ensure_ascii=False)
return len(dados["features"])
def listar_coletas(arquivo):
"""Lista todas as coletas"""
try:
with open(arquivo, "r", encoding="utf-8") as f:
dados = json.load(f)
print("=" * 60)
print("📊 COLETAS CADASTRADAS")
print("=" * 60)
for i, feature in enumerate(dados["features"], start=1):
props = feature["properties"]
coords = feature["geometry"]["coordinates"]
print(f"\n{i}. {props['nome']}")
print(f" Espécie: {props['especie']}")
print(f" Coordenadas: {coords[1]:.4f}°, {coords[0]:.4f}°")
print(f" Profundidade: {props['profundidade_m']}m")
print(f" Temperatura: {props['temperatura_c']}°C")
print("\n" + "=" * 60)
print(f"Total: {len(dados['features'])} coletas")
except FileNotFoundError:
print("❌ Nenhum arquivo encontrado")
# Sistema interativo
def menu():
arquivo = "minhas_coletas.geojson"
while True:
print("\n🌊 SISTEMA DE CADASTRO DE COLETAS")
print("1 - Adicionar coleta")
print("2 - Listar coletas")
print("3 - Sair")
opcao = input("\nEscolha: ")
if opcao == "1":
print("\n📝 Nova Coleta:")
nome = input("Nome da estação: ")
lat = float(input("Latitude: "))
lon = float(input("Longitude: "))
especie = input("Espécie: ")
prof = float(input("Profundidade (m): "))
temp = float(input("Temperatura (°C): "))
coleta = criar_ponto_coleta(nome, lon, lat, especie, prof, temp)
total = adicionar_coleta(arquivo, coleta)
print(f"✅ Coleta adicionada! Total: {total}")
elif opcao == "2":
listar_coletas(arquivo)
elif opcao == "3":
print("👋 Até logo!")
break
if __name__ == "__main__":
menu()
Execute:
python cadastro_coletas.py
🗺️ Visualizar no geojson.io
Depois de criar seus GeoJSON:
- Abra: http://geojson.io
- Arraste seu arquivo
.geojson - Veja no mapa interativo! 🗺️
Ou cole o JSON diretamente no editor.
🎓 Boas Práticas
✅ Faça:
- Use [longitude, latitude] nesta ordem
- Feche polígonos (primeiro = último ponto)
- Valide GeoJSON antes de usar
- Use UTF-8 para acentos
❌ Evite: - Coordenadas invertidas - Polígonos não fechados - Muitos decimais (4-6 é suficiente) - Arquivos gigantes (use simplificação)
🎓 Checklist desta Lição
- [ ] Entendo o que é GeoJSON
- [ ] Sei a diferença entre Point, LineString e Polygon
- [ ] Consigo criar GeoJSON com Python
- [ ] Sei ler e processar arquivos GeoJSON
- [ ] Validei pelo menos um GeoJSON no geojson.io
- [ ] Criei um sistema de cadastro
Se marcou tudo, você está pronto para GeoPandas! 🎉
➡️ Próximo Tópico
Lá você aprenderá: - Usar GeoPandas para análise geoespacial - Operações com geometrias - Análise espacial - Juntar dados geográficos
📝 Resumo de Tipos
| Tipo | Geometria | Uso |
|---|---|---|
| Point | Um ponto | Estação de coleta |
| LineString | Linha | Transecto, rota |
| Polygon | Área | Zona de estudo |
| MultiPoint | Vários pontos | Cluster de coletas |
Você agora domina GeoJSON básico! 🗺️ Próximo: GeoPandas! 🐼
🐼 GeoPandas - Análise Geoespacial com Python
O que é GeoPandas?
GeoPandas = Pandas + Geografia
Pandas GeoPandas
├─ DataFrames ├─ GeoDataFrames (DataFrames + geometria)
├─ Tabelas ├─ Tabelas + mapas
└─ Análise dados └─ Análise espacial
Por que usar: Análise geoespacial com sintaxe familiar de Pandas!
🚀 Instalação
pip install geopandas
pip install matplotlib # Para gráficos
pip install folium # Para mapas interativos (próxima lição)
📊 GeoDataFrame - A Base
Criar GeoDataFrame Simples
import geopandas as gpd
from shapely.geometry import Point
# Dados de coleta
dados = {
'nome': ['Ingleses Norte', 'Ingleses Sul', 'Barra da Lagoa'],
'especie': ['Ulva lactuca', 'Gracilaria', 'Sargassum'],
'profundidade_m': [5.2, 7.8, 3.1],
'temperatura_c': [22.5, 23.1, 22.8]
}
# Criar pontos (geometria)
geometrias = [
Point(-48.3923, -27.4374), # Ingleses Norte
Point(-48.3950, -27.4450), # Ingleses Sul
Point(-48.4200, -27.5750) # Barra da Lagoa
]
# Criar GeoDataFrame
gdf = gpd.GeoDataFrame(dados, geometry=geometrias, crs="EPSG:4326")
print(gdf)
Resultado:
nome especie profundidade_m temperatura_c geometry
0 Ingleses Norte Ulva lactuca 5.2 22.5 POINT (-48.3923 -27.4374)
1 Ingleses Sul Gracilaria 7.8 23.1 POINT (-48.3950 -27.4450)
2 Barra da Lagoa Sargassum 3.1 22.8 POINT (-48.4200 -27.5750)
O que é CRS?
CRS (Coordinate Reference System) = sistema de coordenadas.
EPSG:4326 → WGS84 (GPS padrão - graus decimais)
EPSG:3857 → Web Mercator (Google Maps, Leaflet)
EPSG:31982 → SIRGAS 2000 / UTM 22S (Brasil Sul)
Sempre use EPSG:4326 para dados geográficos básicos!
📥 Carregar Dados Geoespaciais
De GeoJSON
import geopandas as gpd
# Carregar GeoJSON
gdf = gpd.read_file("coletas_LAFIC.geojson")
# Informações
print(gdf.info())
print(gdf.head())
# Ver CRS
print(gdf.crs)
De Shapefile
# Shapefile (formato antigo mas comum)
gdf = gpd.read_file("municipios_sc.shp")
De CSV com Coordenadas
import pandas as pd
import geopandas as gpd
from shapely.geometry import Point
# Carregar CSV
df = pd.read_csv("coletas.csv")
# Colunas: nome, latitude, longitude, especie
# Converter para GeoDataFrame
geometry = [Point(lon, lat) for lon, lat in zip(df['longitude'], df['latitude'])]
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
🗺️ Visualizar Dados
Plot Simples
import geopandas as gpd
import matplotlib.pyplot as plt
# Criar dados
gdf = gpd.read_file("coletas_LAFIC.geojson")
# Plot básico
gdf.plot(figsize=(10, 6), marker='o', color='blue', markersize=50)
plt.title("Estações de Coleta - LAFIC")
plt.xlabel("Longitude")
plt.ylabel("Latitude")
plt.grid(True)
plt.show()
Plot com Cores por Categoria
# Colorir por espécie
gdf.plot(column='especie',
figsize=(10, 6),
legend=True,
markersize=100,
cmap='Set1') # Esquema de cores
plt.title("Distribuição de Espécies")
plt.show()
Plot com Tamanho Variável
# Tamanho proporcional à profundidade
gdf.plot(column='profundidade_m',
figsize=(10, 6),
legend=True,
markersize=gdf['profundidade_m'] * 20, # Multiplicar para visualizar
cmap='YlOrRd') # Amarelo a Vermelho
plt.title("Profundidade das Coletas")
plt.show()
🔧 Operações Básicas
Filtrar Dados
# Filtrar por espécie
ulvas = gdf[gdf['especie'] == 'Ulva lactuca']
print(f"Total de Ulva lactuca: {len(ulvas)}")
# Filtrar por profundidade
rasas = gdf[gdf['profundidade_m'] < 5]
print(f"Coletas rasas (<5m): {len(rasas)}")
# Múltiplas condições
validas = gdf[(gdf['temperatura_c'] >= 20) &
(gdf['temperatura_c'] <= 25) &
(gdf['profundidade_m'] < 10)]
Adicionar Coluna
# Classificar profundidade
def classificar_profundidade(prof):
if prof < 5:
return "Rasa"
elif prof < 20:
return "Intermediária"
else:
return "Profunda"
gdf['classificacao'] = gdf['profundidade_m'].apply(classificar_profundidade)
📐 Operações Geométricas
Calcular Distâncias
from shapely.geometry import Point
# Ponto de referência (LAFIC - UFSC)
LAFIC = Point(-48.5495, -27.5969)
# Calcular distância de cada coleta ao LAFIC
# Nota: distância em graus (aproximação!)
gdf['distancia_graus'] = gdf.geometry.distance(LAFIC)
# Converter para km (1 grau ≈ 111 km)
gdf['distancia_km'] = gdf['distancia_graus'] * 111
print(gdf[['nome', 'distancia_km']])
Criar Buffer (Área ao Redor)
# Criar buffer de 5km ao redor de cada ponto
# Primeiro converter para sistema métrico
gdf_utm = gdf.to_crs("EPSG:31982") # UTM para Santa Catarina
# Buffer de 5000 metros (5km)
gdf_utm['buffer_5km'] = gdf_utm.geometry.buffer(5000)
# Plotar
fig, ax = plt.subplots(figsize=(10, 6))
gdf_utm.plot(ax=ax, color='red', markersize=50)
gdf_utm['buffer_5km'].plot(ax=ax, alpha=0.3, color='blue')
plt.title("Áreas de Influência (5km)")
plt.show()
Verificar se Ponto está Dentro de Polígono
from shapely.geometry import Polygon
# Criar área de estudo (polígono)
area_estudo = Polygon([
(-48.6, -27.4),
(-48.3, -27.4),
(-48.3, -27.7),
(-48.6, -27.7)
])
# Verificar quais pontos estão dentro
gdf['dentro_area'] = gdf.geometry.within(area_estudo)
# Filtrar
dentro = gdf[gdf['dentro_area']]
print(f"Coletas dentro da área: {len(dentro)}")
🎯 Análise Espacial
Encontrar Vizinhos Mais Próximos
import numpy as np
def encontrar_mais_proximo(gdf, idx):
"""Encontra ponto mais próximo a um dado índice"""
ponto = gdf.loc[idx, 'geometry']
# Calcular distâncias
distancias = gdf.geometry.distance(ponto)
# Remover próprio ponto
distancias[idx] = np.inf
# Encontrar mínimo
idx_proximo = distancias.idxmin()
dist_km = distancias[idx_proximo] * 111
return gdf.loc[idx_proximo, 'nome'], dist_km
# Testar
nome, dist = encontrar_mais_proximo(gdf, 0)
print(f"Ponto mais próximo: {nome} ({dist:.2f} km)")
Agrupar por Região
# Dividir em regiões por latitude
gdf['regiao'] = pd.cut(gdf.geometry.y,
bins=3,
labels=['Norte', 'Centro', 'Sul'])
# Estatísticas por região
resumo = gdf.groupby('regiao').agg({
'profundidade_m': 'mean',
'temperatura_c': 'mean',
'especie': 'count'
})
resumo.columns = ['Prof. Média (m)', 'Temp. Média (°C)', 'Num. Coletas']
print(resumo)
💾 Salvar Dados
Para GeoJSON
# Salvar como GeoJSON
gdf.to_file("resultado_analise.geojson", driver="GeoJSON")
Para Shapefile
# Salvar como Shapefile
gdf.to_file("resultado_analise.shp")
Para CSV (sem geometria)
# Adicionar colunas de coordenadas
gdf['longitude'] = gdf.geometry.x
gdf['latitude'] = gdf.geometry.y
# Salvar só os dados
gdf.drop(columns=['geometry']).to_csv("resultado.csv", index=False)
🌍 Exemplo Completo: Análise de Distribuição de Espécies
import geopandas as gpd
import matplotlib.pyplot as plt
import pandas as pd
from shapely.geometry import Point
# 1. CRIAR DADOS DE EXEMPLO (LAFIC)
dados = {
'id': range(1, 11),
'local': [
'Ingleses N', 'Ingleses S', 'Barra Lagoa', 'Laguna',
'Garopaba', 'Armação', 'Campeche', 'Pântano Sul',
'Joaquina', 'Mole'
],
'especie': [
'Ulva lactuca', 'Gracilaria', 'Sargassum', 'Ulva lactuca',
'Gracilaria', 'Ulva lactuca', 'Sargassum', 'Laminaria',
'Ulva lactuca', 'Gracilaria'
],
'profundidade_m': [5.2, 7.8, 3.1, 10.5, 6.0, 4.5, 8.2, 12.0, 5.5, 7.0],
'temperatura_c': [22.5, 23.1, 22.8, 21.2, 22.0, 23.5, 22.9, 20.5, 23.0, 22.7],
'longitude': [-48.39, -48.40, -48.42, -48.78, -48.62, -48.51, -48.48, -48.50, -48.44, -48.43],
'latitude': [-27.44, -27.45, -27.58, -28.48, -28.02, -27.75, -27.67, -27.78, -27.63, -27.58]
}
df = pd.DataFrame(dados)
# 2. CRIAR GEODATAFRAME
geometry = [Point(lon, lat) for lon, lat in zip(df['longitude'], df['latitude'])]
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
print("=" * 70)
print("🌊 ANÁLISE DE DISTRIBUIÇÃO DE MACROALGAS - LAFIC/UFSC")
print("=" * 70)
# 3. ESTATÍSTICAS GERAIS
print(f"\n📊 Dados Gerais:")
print(f" Total de coletas: {len(gdf)}")
print(f" Espécies únicas: {gdf['especie'].nunique()}")
print(f" Profundidade média: {gdf['profundidade_m'].mean():.1f}m")
print(f" Temperatura média: {gdf['temperatura_c'].mean():.1f}°C")
# 4. ANÁLISE POR ESPÉCIE
print(f"\n🌿 Distribuição por Espécie:")
especies_count = gdf['especie'].value_counts()
for especie, count in especies_count.items():
print(f" {especie}: {count} coletas")
# 5. CALCULAR CENTROIDE (centro geográfico)
centroide = gdf.geometry.unary_union.centroid
print(f"\n📍 Centro Geográfico das Coletas:")
print(f" Latitude: {centroide.y:.4f}°")
print(f" Longitude: {centroide.x:.4f}°")
# 6. FILTRAR E ANALISAR
print(f"\n✓ Coletas Validadas (20-25°C, <10m):")
validas = gdf[(gdf['temperatura_c'] >= 20) &
(gdf['temperatura_c'] <= 25) &
(gdf['profundidade_m'] < 10)]
print(f" {len(validas)}/{len(gdf)} coletas válidas ({len(validas)/len(gdf)*100:.0f}%)")
# 7. VISUALIZAÇÃO
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
# Subplot 1: Todas as coletas
gdf.plot(ax=axes[0], marker='o', color='blue', markersize=100, alpha=0.6)
axes[0].set_title("Todas as Estações de Coleta", fontsize=12)
axes[0].set_xlabel("Longitude")
axes[0].set_ylabel("Latitude")
axes[0].grid(True, alpha=0.3)
# Subplot 2: Por espécie
gdf.plot(ax=axes[1], column='especie', legend=True,
markersize=100, cmap='Set1', alpha=0.7)
axes[1].set_title("Distribuição por Espécie", fontsize=12)
axes[1].set_xlabel("Longitude")
axes[1].grid(True, alpha=0.3)
# Subplot 3: Por profundidade
gdf.plot(ax=axes[2], column='profundidade_m', legend=True,
markersize=100, cmap='YlOrRd', alpha=0.7)
axes[2].set_title("Profundidade das Coletas", fontsize=12)
axes[2].set_xlabel("Longitude")
axes[2].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("analise_distribuicao.png", dpi=300, bbox_inches='tight')
print(f"\n💾 Gráfico salvo: analise_distribuicao.png")
# 8. SALVAR RESULTADOS
gdf.to_file("coletas_analisadas.geojson", driver="GeoJSON")
print(f"💾 GeoJSON salvo: coletas_analisadas.geojson")
print("\n" + "=" * 70)
print("✅ Análise concluída com sucesso!")
🎓 Checklist desta Lição
- [ ] Entendo o que é GeoDataFrame
- [ ] Consigo criar GeoDataFrame de dados
- [ ] Sei carregar e salvar GeoJSON
- [ ] Posso fazer operações geométricas (buffer, distância)
- [ ] Consigo visualizar dados em mapas
- [ ] Realizei análise espacial completa
Se marcou tudo, você está pronto para Mapas Interativos! 🎉
➡️ Próximo Tópico
Lá você aprenderá: - Criar mapas interativos com Folium - Adicionar marcadores e popups - Camadas e clusters - Publicar mapas online
📝 Resumo de Funções
| Função | Uso |
|---|---|
gpd.read_file() |
Carregar GeoJSON/Shapefile |
gdf.plot() |
Visualizar mapa |
gdf.to_file() |
Salvar arquivo geoespacial |
geometry.distance() |
Calcular distância |
geometry.buffer() |
Criar área ao redor |
geometry.within() |
Verificar se está dentro |
Você domina GeoPandas básico! 🐼 Próximo: Mapas interativos com Folium! 🗺️
🗺️ Mapas Interativos com Folium
O que é Folium?
Folium = biblioteca Python para criar mapas interativos web (Leaflet.js).
GeoPandas Folium
├─ Análise ├─ Visualização
├─ Mapas estáticos ├─ Mapas interativos
└─ PNG/PDF └─ HTML (web)
Use para: Publicar resultados, apresentações, dashboards web
🚀 Instalação
pip install folium
pip install geopandas # Se ainda não tem
🎯 Criar Mapa Básico
Exemplo Mínimo
import folium
# Criar mapa centrado em Florianópolis
mapa = folium.Map(
location=[-27.5969, -48.5495], # [latitude, longitude]
zoom_start=12,
tiles='OpenStreetMap'
)
# Salvar como HTML
mapa.save("meu_primeiro_mapa.html")
print("✅ Mapa criado: meu_primeiro_mapa.html")
Abra o arquivo HTML no navegador! 🌐
Tipos de Tiles (Camadas Base)
import folium
# OpenStreetMap (padrão)
mapa1 = folium.Map(location=[-27.5969, -48.5495], zoom_start=12,
tiles='OpenStreetMap')
# Imagem de satélite
mapa2 = folium.Map(location=[-27.5969, -48.5495], zoom_start=12,
tiles='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
attr='Esri')
# CartoDB Positron (minimalista)
mapa3 = folium.Map(location=[-27.5969, -48.5495], zoom_start=12,
tiles='CartoDB positron')
# Stamen Terrain (topografia)
mapa4 = folium.Map(location=[-27.5969, -48.5495], zoom_start=12,
tiles='Stamen Terrain')
📍 Adicionar Marcadores
Marcador Simples
import folium
# Criar mapa
mapa = folium.Map(location=[-27.5969, -48.5495], zoom_start=12)
# Adicionar marcador
folium.Marker(
location=[-27.4374, -48.3923],
popup="Praia dos Ingleses",
tooltip="Clique para mais informações",
icon=folium.Icon(color='blue', icon='info-sign')
).add_to(mapa)
mapa.save("mapa_com_marcador.html")
Marcadores com Ícones Personalizados
import folium
mapa = folium.Map(location=[-27.5969, -48.5495], zoom_start=11)
# Ícone padrão - vermelho
folium.Marker(
[-27.4374, -48.3923],
popup="Ulva lactuca - Profundidade: 5.2m",
icon=folium.Icon(color='red', icon='leaf', prefix='fa')
).add_to(mapa)
# Ícone verde
folium.Marker(
[-27.4450, -48.3950],
popup="Gracilaria - Profundidade: 7.8m",
icon=folium.Icon(color='green', icon='seedling', prefix='fa')
).add_to(mapa)
# Ícone azul
folium.Marker(
[-27.5750, -48.4200],
popup="Sargassum - Profundidade: 3.1m",
icon=folium.Icon(color='blue', icon='water', prefix='fa')
).add_to(mapa)
mapa.save("mapa_especies.html")
Cores disponíveis: red, blue, green, purple, orange, darkred, lightred, beige, darkblue, darkgreen, cadetblue, darkpurple, white, pink, lightblue, lightgreen, gray, black, lightgray
🎨 Popups e Tooltips Avançados
Popup com HTML
import folium
mapa = folium.Map(location=[-27.5969, -48.5495], zoom_start=12)
# HTML formatado
html = """
<div style="font-family: Arial; width: 200px;">
<h4 style="color: #2E86AB;">Estação 1 - Ingleses</h4>
<hr>
<b>Espécie:</b> <i>Ulva lactuca</i><br>
<b>Profundidade:</b> 5.2m<br>
<b>Temperatura:</b> 22.5°C<br>
<b>Salinidade:</b> 35.0 PSU<br>
<hr>
<small>Data: 06/01/2025</small>
</div>
"""
folium.Marker(
[-27.4374, -48.3923],
popup=folium.Popup(html, max_width=300),
tooltip="Clique para detalhes"
).add_to(mapa)
mapa.save("mapa_popup_html.html")
Popup com Gráfico (Avançado)
import folium
import base64
from io import BytesIO
import matplotlib.pyplot as plt
mapa = folium.Map(location=[-27.5969, -48.5495], zoom_start=12)
# Criar mini-gráfico
fig, ax = plt.subplots(figsize=(4, 2))
temps = [22.5, 23.1, 22.8, 23.4, 22.9]
ax.plot(temps, marker='o', color='#2E86AB')
ax.set_title("Temperatura (últimos 5 dias)")
ax.set_ylabel("°C")
ax.grid(True, alpha=0.3)
# Salvar como PNG em memória
buffer = BytesIO()
plt.savefig(buffer, format='png', bbox_inches='tight', dpi=100)
buffer.seek(0)
image_base64 = base64.b64encode(buffer.read()).decode()
plt.close()
# Criar HTML com imagem
html = f"""
<div style="font-family: Arial;">
<h4>Estação 1</h4>
<img src="data:image/png;base64,{image_base64}" width="300">
</div>
"""
folium.Marker(
[-27.4374, -48.3923],
popup=folium.Popup(html, max_width=350)
).add_to(mapa)
mapa.save("mapa_popup_grafico.html")
🌐 Adicionar Múltiplos Pontos de GeoDataFrame
Integração com GeoPandas
import folium
import geopandas as gpd
from shapely.geometry import Point
# Criar dados
dados = {
'nome': ['Ingleses N', 'Ingleses S', 'Barra Lagoa', 'Laguna'],
'especie': ['Ulva lactuca', 'Gracilaria', 'Sargassum', 'Laminaria'],
'profundidade_m': [5.2, 7.8, 3.1, 10.5],
'temperatura_c': [22.5, 23.1, 22.8, 21.2]
}
geometry = [
Point(-48.3923, -27.4374),
Point(-48.3950, -27.4450),
Point(-48.4200, -27.5750),
Point(-48.7833, -28.4833)
]
gdf = gpd.GeoDataFrame(dados, geometry=geometry, crs="EPSG:4326")
# Criar mapa
mapa = folium.Map(location=[-27.8, -48.5], zoom_start=9)
# Adicionar cada ponto
for idx, row in gdf.iterrows():
# Popup com informações
popup_html = f"""
<b>{row['nome']}</b><br>
Espécie: <i>{row['especie']}</i><br>
Profundidade: {row['profundidade_m']}m<br>
Temperatura: {row['temperatura_c']}°C
"""
folium.Marker(
location=[row.geometry.y, row.geometry.x],
popup=folium.Popup(popup_html, max_width=200),
tooltip=row['nome'],
icon=folium.Icon(color='blue', icon='leaf', prefix='fa')
).add_to(mapa)
mapa.save("mapa_geodataframe.html")
print("✅ Mapa criado com dados GeoPandas")
🎨 Marcadores com Cores Dinâmicas
Colorir por Categoria
import folium
import geopandas as gpd
from shapely.geometry import Point
# Dados
gdf = gpd.GeoDataFrame({
'nome': ['Local 1', 'Local 2', 'Local 3', 'Local 4'],
'especie': ['Ulva', 'Gracilaria', 'Ulva', 'Sargassum'],
'geometry': [Point(-48.39, -27.44), Point(-48.40, -27.45),
Point(-48.42, -27.58), Point(-48.78, -28.48)]
}, crs="EPSG:4326")
# Mapa de cores por espécie
cores_especies = {
'Ulva': 'green',
'Gracilaria': 'red',
'Sargassum': 'blue'
}
mapa = folium.Map(location=[-27.8, -48.5], zoom_start=9)
for idx, row in gdf.iterrows():
cor = cores_especies.get(row['especie'], 'gray')
folium.Marker(
[row.geometry.y, row.geometry.x],
popup=f"{row['nome']}: {row['especie']}",
icon=folium.Icon(color=cor, icon='leaf', prefix='fa')
).add_to(mapa)
mapa.save("mapa_cores_especies.html")
⭕ CircleMarkers (Círculos)
Tamanho Proporcional a Valor
import folium
import geopandas as gpd
from shapely.geometry import Point
gdf = gpd.GeoDataFrame({
'nome': ['Est. 1', 'Est. 2', 'Est. 3'],
'profundidade_m': [5.2, 12.8, 3.1],
'geometry': [Point(-48.39, -27.44), Point(-48.40, -27.45), Point(-48.42, -27.58)]
}, crs="EPSG:4326")
mapa = folium.Map(location=[-27.5, -48.4], zoom_start=11)
for idx, row in gdf.iterrows():
# Raio proporcional à profundidade
raio = row['profundidade_m'] * 2 # Multiplicar para visualizar melhor
folium.CircleMarker(
location=[row.geometry.y, row.geometry.x],
radius=raio,
popup=f"{row['nome']}<br>Prof: {row['profundidade_m']}m",
color='blue',
fill=True,
fillColor='cyan',
fillOpacity=0.6
).add_to(mapa)
mapa.save("mapa_circle_markers.html")
🗂️ Grupos e Camadas
Controle de Camadas
import folium
mapa = folium.Map(location=[-27.5969, -48.5495], zoom_start=11)
# Criar grupos de camadas
grupo_ulva = folium.FeatureGroup(name='Ulva lactuca')
grupo_gracilaria = folium.FeatureGroup(name='Gracilaria')
# Adicionar marcadores aos grupos
folium.Marker(
[-27.4374, -48.3923],
popup="Ulva - Local 1",
icon=folium.Icon(color='green')
).add_to(grupo_ulva)
folium.Marker(
[-27.4450, -48.3950],
popup="Ulva - Local 2",
icon=folium.Icon(color='green')
).add_to(grupo_ulva)
folium.Marker(
[-27.5750, -48.4200],
popup="Gracilaria - Local 1",
icon=folium.Icon(color='red')
).add_to(grupo_gracilaria)
# Adicionar grupos ao mapa
grupo_ulva.add_to(mapa)
grupo_gracilaria.add_to(mapa)
# Adicionar controle de camadas
folium.LayerControl().add_to(mapa)
mapa.save("mapa_com_camadas.html")
📊 Heatmap (Mapa de Calor)
import folium
from folium.plugins import HeatMap
# Dados: [latitude, longitude, intensidade]
dados_calor = [
[-27.4374, -48.3923, 0.8],
[-27.4450, -48.3950, 0.6],
[-27.5750, -48.4200, 0.9],
[-27.4400, -48.3930, 0.7],
[-27.4500, -48.4000, 0.5]
]
mapa = folium.Map(location=[-27.5, -48.4], zoom_start=11)
# Adicionar heatmap
HeatMap(dados_calor, radius=20, blur=25, max_zoom=13).add_to(mapa)
mapa.save("mapa_heatmap.html")
🎯 Exemplo Completo: Dashboard de Coletas
import folium
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point
from folium.plugins import MarkerCluster
# 1. PREPARAR DADOS
dados = {
'id': range(1, 11),
'local': ['Ingleses N', 'Ingleses S', 'Barra Lagoa', 'Laguna',
'Garopaba', 'Armação', 'Campeche', 'Pântano Sul',
'Joaquina', 'Mole'],
'especie': ['Ulva lactuca', 'Gracilaria', 'Sargassum', 'Ulva lactuca',
'Gracilaria', 'Ulva lactuca', 'Sargassum', 'Laminaria',
'Ulva lactuca', 'Gracilaria'],
'profundidade_m': [5.2, 7.8, 3.1, 10.5, 6.0, 4.5, 8.2, 12.0, 5.5, 7.0],
'temperatura_c': [22.5, 23.1, 22.8, 21.2, 22.0, 23.5, 22.9, 20.5, 23.0, 22.7],
'longitude': [-48.39, -48.40, -48.42, -48.78, -48.62, -48.51, -48.48, -48.50, -48.44, -48.43],
'latitude': [-27.44, -27.45, -27.58, -28.48, -28.02, -27.75, -27.67, -27.78, -27.63, -27.58]
}
df = pd.DataFrame(dados)
geometry = [Point(lon, lat) for lon, lat in zip(df['longitude'], df['latitude'])]
gdf = gpd.GeoDataFrame(df, geometry=geometry, crs="EPSG:4326")
# 2. CONFIGURAR MAPA
mapa = folium.Map(
location=[-27.8, -48.5],
zoom_start=9,
tiles='OpenStreetMap'
)
# 3. DEFINIR CORES POR ESPÉCIE
cores_especies = {
'Ulva lactuca': 'green',
'Gracilaria': 'red',
'Sargassum': 'blue',
'Laminaria': 'purple'
}
# 4. CRIAR GRUPOS DE CAMADAS
grupos = {}
for especie in gdf['especie'].unique():
grupos[especie] = folium.FeatureGroup(name=especie)
# 5. ADICIONAR MARCADORES
for idx, row in gdf.iterrows():
# Determinar status de validação
valida = (20 <= row['temperatura_c'] <= 25) and (row['profundidade_m'] < 10)
status = "✅ VÁLIDA" if valida else "⚠️ ATENÇÃO"
# HTML do popup
popup_html = f"""
<div style="font-family: Arial; width: 220px;">
<h4 style="color: #2E86AB; margin-bottom: 8px;">
📍 {row['local']}
</h4>
<hr style="margin: 5px 0;">
<table style="width: 100%; font-size: 12px;">
<tr>
<td><b>ID:</b></td>
<td>{row['id']}</td>
</tr>
<tr>
<td><b>Espécie:</b></td>
<td><i>{row['especie']}</i></td>
</tr>
<tr>
<td><b>Profundidade:</b></td>
<td>{row['profundidade_m']}m</td>
</tr>
<tr>
<td><b>Temperatura:</b></td>
<td>{row['temperatura_c']}°C</td>
</tr>
<tr>
<td><b>Coordenadas:</b></td>
<td>{row['latitude']:.4f}°, {row['longitude']:.4f}°</td>
</tr>
</table>
<hr style="margin: 5px 0;">
<div style="text-align: center; padding: 5px; background-color: {'#d4edda' if valida else '#fff3cd'}; border-radius: 3px;">
<b>{status}</b>
</div>
</div>
"""
# Criar marcador
cor = cores_especies.get(row['especie'], 'gray')
marcador = folium.Marker(
location=[row['latitude'], row['longitude']],
popup=folium.Popup(popup_html, max_width=300),
tooltip=f"{row['local']} - {row['especie']}",
icon=folium.Icon(color=cor, icon='leaf', prefix='fa')
)
# Adicionar ao grupo correspondente
marcador.add_to(grupos[row['especie']])
# 6. ADICIONAR GRUPOS AO MAPA
for grupo in grupos.values():
grupo.add_to(mapa)
# 7. ADICIONAR CONTROLE DE CAMADAS
folium.LayerControl(position='topright', collapsed=False).add_to(mapa)
# 8. ADICIONAR TÍTULO
titulo_html = '''
<div style="position: fixed;
top: 10px;
left: 50px;
width: 400px;
height: auto;
background-color: white;
border: 2px solid #2E86AB;
border-radius: 5px;
z-index: 9999;
padding: 10px;
font-family: Arial;">
<h3 style="margin: 0; color: #2E86AB;">
🌊 Distribuição de Macroalgas - LAFIC/UFSC
</h3>
<p style="margin: 5px 0; font-size: 12px;">
Total de coletas: <b>{}</b> | Espécies: <b>{}</b>
</p>
</div>
'''.format(len(gdf), gdf['especie'].nunique())
mapa.get_root().html.add_child(folium.Element(titulo_html))
# 9. SALVAR
mapa.save("dashboard_coletas_LAFIC.html")
print("✅ Dashboard criado: dashboard_coletas_LAFIC.html")
print(f"📊 {len(gdf)} coletas mapeadas")
print(f"🌿 {gdf['especie'].nunique()} espécies diferentes")
Execute e abra o arquivo HTML! 🚀
🎓 Checklist desta Lição
- [ ] Criei mapa básico com Folium
- [ ] Adicionei marcadores com popups
- [ ] Integrei GeoPandas com Folium
- [ ] Usei cores e ícones personalizados
- [ ] Criei camadas controláveis
- [ ] Desenvolvi dashboard completo
Se marcou tudo, você completou Análise Geoespacial! 🎉
➡️ Próximos Passos
Parabéns! Você domina análise geoespacial com Python! 🗺️
Próximos módulos: 1. Visualização Web (HTML, JavaScript avançado) 2. Casos Práticos (Aplicações reais em Oceanografia)
📝 Resumo de Funções Folium
| Função | Uso |
|---|---|
folium.Map() |
Criar mapa base |
folium.Marker() |
Adicionar marcador |
folium.CircleMarker() |
Círculo proporcional |
folium.Popup() |
Popup HTML |
folium.FeatureGroup() |
Grupo de camadas |
folium.LayerControl() |
Controle de camadas |
HeatMap() |
Mapa de calor |
Você é um expert em mapas interativos! 🗺️✨
Abra seus mapas HTML no navegador e compartilhe com sua equipe do LAFIC! 🌊