Introducción
Esta práctica demuestra un ejemplo de consulta basada en vecinos (en particular, una estimación de densidad de núcleo) sobre datos geográficos, utilizando un árbol de búsqueda Ball construido sobre la métrica de distancia de Haversine, es decir, distancias entre puntos en latitud/longitud. El conjunto de datos es proporcionado por Phillips et. al. (2006). El ejemplo utiliza la librería basemap para trazar las líneas de costa y los límites nacionales de Sudamérica.
Consejos sobre la VM
Una vez finalizada la inicialización de la VM, haga clic en la esquina superior izquierda para cambiar a la pestaña Cuaderno y acceder a Jupyter Notebook para practicar.
A veces, es posible que tenga que esperar unos segundos a que Jupyter Notebook termine de cargarse. La validación de las operaciones no se puede automatizar debido a las limitaciones de Jupyter Notebook.
Si tiene problemas durante el aprendizaje, no dude en preguntar a Labby. Deje sus comentarios después de la sesión y resolveremos rápidamente el problema para usted.
Importar las bibliotecas necesarias
El primer paso es importar las bibliotecas necesarias para esta práctica. En esta práctica utilizaremos las bibliotecas numpy, matplotlib, fetch_species_distributions y KernelDensity.
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_species_distributions
from sklearn.neighbors import KernelDensity
Cargar datos
El siguiente paso es cargar los datos proporcionados por Phillips et. al. (2006). El conjunto de datos contiene dos especies que utilizaremos para demostrar la estimación de densidad de núcleo.
data = fetch_species_distributions()
species_names = ["Bradypus Variegatus", "Microryzomys Minutus"]
Preparar los datos
Ahora prepararemos los datos para la estimación de densidad de núcleo. Extraeremos la información de latitud y longitud del conjunto de datos y la convertiremos a radianes.
Xtrain = np.vstack([data["train"]["dd lat"], data["train"]["dd long"]]).T
ytrain = np.array(
[d.decode("ascii").startswith("micro") for d in data["train"]["species"]],
dtype="int",
)
Xtrain *= np.pi / 180.0 ## Convertir lat/long a radianes
Construir la malla
Ahora construiremos la malla del mapa a partir del objeto de lote. Utilizaremos la función construct_grids para lograr esto.
def construct_grids(batch):
"""Construir la malla del mapa a partir del objeto de lote
Parámetros
----------
batch : Objeto de lote
El objeto devuelto por :func:`fetch_species_distributions`
Devuelve
-------
(xgrid, ygrid) : Arrays unidimensionales
La malla correspondiente a los valores en batch.coverages
"""
## Coordenadas x,y para las celdas de esquina
xmin = batch.x_left_lower_corner + batch.grid_size
xmax = xmin + (batch.Nx * batch.grid_size)
ymin = batch.y_left_lower_corner + batch.grid_size
ymax = ymin + (batch.Ny * batch.grid_size)
## Coordenadas x de las celdas de la malla
xgrid = np.arange(xmin, xmax, batch.grid_size)
## Coordenadas y de las celdas de la malla
ygrid = np.arange(ymin, ymax, batch.grid_size)
return (xgrid, ygrid)
## Llame a la función y almacene los resultados en xgrid e ygrid
xgrid, ygrid = construct_grids(data)
Preparar la malla de datos
Configuraremos la malla de datos para el gráfico de contornos. Utilizaremos la función construct_grids para lograr esto.
X, Y = np.meshgrid(xgrid[::5], ygrid[::5][::-1])
land_reference = data.coverages[6][::5, ::5]
land_mask = (land_reference > -9999).ravel()
xy = np.vstack([Y.ravel(), X.ravel()]).T
xy = xy[land_mask]
xy *= np.pi / 180.0
Graficar el mapa de Sudamérica
Ahora graficaremos el mapa de Sudamérica con las distribuciones de cada especie.
fig = plt.figure()
fig.subplots_adjust(left=0.05, right=0.95, wspace=0.05)
for i in range(2):
plt.subplot(1, 2, i + 1)
print(" - calculando KDE en coordenadas esféricas")
kde = KernelDensity(
bandwidth=0.04, metric="haversine", kernel="gaussian", algorithm="ball_tree"
)
kde.fit(Xtrain[ytrain == i])
Z = np.full(land_mask.shape[0], -9999, dtype="int")
Z[land_mask] = np.exp(kde.score_samples(xy))
Z = Z.reshape(X.shape)
levels = np.linspace(0, Z.max(), 25)
plt.contourf(X, Y, Z, levels=levels, cmap=plt.cm.Reds)
if basemap:
print(" - graficar costas usando basemap")
m = Basemap(
projection="cyl",
llcrnrlat=Y.min(),
urcrnrlat=Y.max(),
llcrnrlon=X.min(),
urcrnrlon=X.max(),
resolution="c",
)
m.drawcoastlines()
m.drawcountries()
else:
print(" - graficar costas a partir de cobertura")
plt.contour(
X, Y, land_reference, levels=[-9998], colors="k", linestyles="solid"
)
plt.xticks([])
plt.yticks([])
plt.title(species_names[i])
plt.show()
Resumen
En este laboratorio, aprendimos cómo realizar una estimación de densidad de núcleo en datos geográficos. Utilizamos el conjunto de datos de Phillips et. al. (2006) para demostrar esta técnica. También aprendimos cómo graficar el mapa de Sudamérica con las distribuciones de cada especie utilizando la biblioteca basemap.