寻找支持2D三角分箱的Python工具及高效点归属判断方案
2D三角分箱的Python工具与高效实现方案
现成工具替代方案
目前没有直接对标scipy.stats.binned_statistic_dd的三角分箱专用包,但可以组合现有工具实现类似功能:
- 用
matplotlib.tri.Triangulation生成三角网格,结合numpy向量化操作或scipy.spatial的空间索引,自行实现分箱统计逻辑,满足三角分箱的统计需求。 - 若只需可视化+基础统计,可基于
matplotlib.tri的三角网格,手动统计每个三角内的点数、均值等指标。
自行实现的高效点-in-三角判断(10万级数据)
针对大规模数据集,核心是避免Python循环,通过向量化运算+空间索引优化性能:
1. 向量化重心坐标判断
利用numpy广播机制,一次性完成所有点与所有三角的归属判断,核心原理是通过重心坐标参数判断点是否在三角内部:
import numpy as np def point_in_triangles(points, triangles): # points: 形状为(N, 2)的点数组 # triangles: 形状为(M, 3, 2)的三角顶点数组,每个三角存储三个(x,y)坐标 A = triangles[:, 0, :] B = triangles[:, 1, :] C = triangles[:, 2, :] # 计算向量与点积 v0 = C - A v1 = B - A v2 = points[:, np.newaxis, :] - A dot00 = (v0 * v0).sum(axis=2) dot01 = (v0 * v1).sum(axis=2) dot02 = (v0 * v2).sum(axis=2) dot11 = (v1 * v1).sum(axis=2) dot12 = (v1 * v2).sum(axis=2) # 计算重心坐标的u、v参数 inv_denom = 1 / (dot00 * dot11 - dot01 * dot01) u = (dot11 * dot02 - dot01 * dot12) * inv_denom v = (dot00 * dot12 - dot01 * dot02) * inv_denom # 判断点是否在三角内(含边界) return (u >= 0) & (v >= 0) & (u + v <= 1)
调用后会得到(N, M)的布尔数组,其中result[i,j]表示第i个点是否属于第j个三角。后续可通过numpy.argmax或掩码操作提取每个点对应的三角索引(需处理点不在任何三角的异常情况)。
2. 空间索引缩小候选范围
直接对所有三角做向量化判断仍可能存在性能瓶颈,可先通过空间索引筛选候选三角:
- 用
scipy.spatial.cKDTree为三角的包围盒中心构建索引,查询每个点附近的K个三角,只对这些候选三角做精确判断,大幅减少计算量。 - 或者预先将平面划分为粗粒度矩形网格,把三角分配到对应的网格单元,点先定位到网格单元,再仅在单元内的三角中判断归属。
3. 结合分箱统计
拿到每个点的三角索引后,即可用numpy.bincount或scipy.stats.binned_statistic完成均值、求和等统计操作,实现类似binned_statistic_dd的功能。
内容的提问来源于stack exchange,提问作者jpmorr
相关产品推荐
相关产品推荐

