本例展示了如何使用基于邻居的查询(特别是核密度估计)来处理地理空间数据,使用基于Haversine距离度量的球面坐标。数据集由Phillips等人(2006年)提供。如果可用,示例将使用basemap来绘制南美洲的海岸线和国界。
本示例不执行数据上的任何学习(有关基于此数据集属性的分类示例,请参阅物种分布建模)。它仅显示了在地理坐标中观察到的数据点的核密度估计。这里涉及的两个物种是:
“Bradypus variegatus”,即棕喉树懒。这是一种生活在南美洲的哺乳动物,以其缓慢的动作和悠闲的生活方式而闻名。
“Microryzomys minutus”,也称为森林小稻鼠,是一种生活在秘鲁、哥伦比亚、厄瓜多尔和委内瑞拉的啮齿类动物。
在进行核密度估计之前,首先需要构建地图网格。这可以通过从数据集中获取的批量对象来完成。使用球面坐标来计算核密度估计,并从覆盖范围中绘制海岸线。
以下是实现这一过程的Python代码示例:
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import fetch_species_distributions
from sklearn.neighbors import KernelDensity
try:
from mpl_toolkits.basemap import Basemap
basemap = True
except ImportError:
basemap = False
def construct_grids(batch):
""“构建地图网格”""
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)
xgrid = np.arange(xmin, xmax, batch.grid_size)
ygrid = np.arange(ymin, ymax, batch.grid_size)
return xgrid, ygrid
# 获取物种ID和位置的矩阵/数组
data = fetch_species_distributions()
species_names = ["Bradypus Variegatus", "Microryzomys Minutus"]
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 # 将经纬度转换为弧度
# 为等高线图设置数据网格
xgrid, ygrid = construct_grids(data)
X, Y = np.meshgrid(xgrid[::5], ygrid[::-1][::5])
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
# 绘制南美洲的地图和每个物种的分布
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("- 计算球面坐标中的KDE")
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("- 使用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("- 从覆盖范围绘制海岸线")
plt.contour(X, Y, land_reference, levels=[-9998], colors="k", linestyles="solid")
plt.xticks([])
plt.yticks([])
plt.title(species_names[i])
plt.show()
这段代码首先导入了必要的库,然后定义了一个函数来构建地图网格。接着,它获取了物种ID和位置的数据,并将其转换为弧度。然后,它设置了一个数据网格,并使用核密度估计来计算每个物种的分布。最后,它绘制了南美洲的地图和每个物种的分布。
请注意,这个示例假设已经安装了所有必要的库,包括matplotlib、numpy、sklearn和basemap(如果可用)。如果没有安装basemap,代码将使用其他方法来绘制海岸线。