这个问题是在我使用的显示最终解决方案的答案之后编辑的
我有来自不同来源的非结构化 2D 数据集,例如:
这些数据集是 3 个 numpy.ndarray(X、Y 坐标和 Z 值)。
我的最终目标是在网格上插入这些数据以转换为图像/矩阵。所以,我需要找到插入这些数据的“最佳网格”。而且,为此,我需要在该网格的像素之间找到最佳的 X 和 Y 步长。
根据点之间的欧几里德距离确定步长:
使用每个点与其最近邻点之间的欧几里得距离的平均值。
- 使用
KDTree
/cKDTree
来自 scipy.spacial 构建 X、Y 数据树。 - 使用for
query
方法k=2
获取距离(如果k=1
,距离仅为零,因为对每个点的查询都找到了自己)。
# Generate KD Tree
xy = np.c_[x, y] # X,Y data converted for use with KDTree
tree = scipy.spacial.cKDTree(xy) # Create KDtree for X,Y coordinates.
# Calculate step
distances, points = tree.query(xy, k=2) # Query distances for X,Y points
distances = distances[:, 1:] # Remove k=1 zero distances
step = numpy.mean(distances) # Result
性能调整:
- 使用
scipy.spatial.cKDTree
而不是scipy.spatial.KDTree
因为它真的更快。 balanced_tree=False
与 一起使用scipy.spatial.cKDTree
:在我的情况下可以大大加快速度,但可能并非对所有数据都适用。- 使用
n_jobs=-1
withcKDTree.query
用于使用多线程。 - 使用
p=1
withcKDTree.query
for use 曼哈顿距离代替欧几里得距离 (p=2
):更快但可能不太准确。 - 仅查询点的随机子样本的距离:使用大型数据集可大大加快速度,但可能不太准确且可重复性较差。
在网格上插入点:
使用计算的步骤在网格上插入数据集点。
# Generate grid
def interval(axe):
'''Return numpy.linspace Interval for specified axe'''
cent = axe.min() + axe.ptp() / 2 # Interval center
nbs = np.ceil(axe.ptp() / step) # Number of step in interval
hwid = nbs * step / 2 # Half interval width
return np.linspace(cent - hwid, cent + hwid, nbs) # linspace
xg, yg = np.meshgrid(interval(x), interval(y)) # Generate grid
# Interpolate X,Y,Z datas on grid
zg = scipy.interpolate.griddata((x, y), z, (xg, yg))
如果像素离初始点太远,则设置 NaN:
将 NaN 设置为与初始 X、Y、Z 数据中的点相距太远(距离 > 步长)的网格像素。使用之前生成的 KDTree。
# Calculate pixel to X,Y,Z data distances
dist, _ = tree.query(np.c_[xg.ravel(), yg.ravel()])
dist = dist.reshape(xg.shape)
# Set NaN value for too far pixels
zg[dist > step] = np.nan