计算缺少值的scipy中的成对距离
问题内容:
我对如何scipy.spatial.distance.pdist
处理缺少的(nan
)值感到困惑。
因此,以防万一我弄乱了矩阵的尺寸,让我们避免它。从文档:
这些点在矩阵X中排列为m个n维行向量。
因此,让我们在10维空间中生成三个缺少值的点:
numpy.random.seed(123456789)
data = numpy.random.rand(3, 10) * 5
data[data < 1.0] = numpy.nan
如果我计算这三个观测值的欧几里得距离:
pdist(data, "euclidean")
我得到:
数组([nan,nan,nan])
但是,如果我过滤所有缺少值的列,则可以得到正确的距离值:
valid = [i for (i, col) in enumerate(data.T) if ~numpy.isnan(col).any()]
pdist(data[:, valid], "euclidean")
我得到:
数组([3.35518662,2.35481185,3.10323893])
这样一来,由于不需要过滤整个矩阵,而一次只比较一对向量,因此我丢弃了比我想要的更多的数据。我可以使pdist
某种类似的功能执行成对屏蔽吗?
编辑:
由于我的完整矩阵很大,因此我对此处提供的小型数据集进行了一些时序测试。
1.)scipy功能。
%timeit pdist(data, "euclidean")
10000个循环,最好为3:每个循环24.4 µs
2.)不幸的是,到目前为止提供的解决方案要慢大约10倍。
%timeit numpy.array([pdist(data[s][:, ~numpy.isnan(data[s]).any(axis=0)], "euclidean") for s in map(list, itertools.combinations(range(data.shape[0]), 2))]).ravel()
1000个循环,最好为3:每个循环231 µs
3.)然后,我对“纯” Python进行了测试,并感到惊喜:
from scipy.linalg import norm
%%timeit
m = data.shape[0]
dm = numpy.zeros(m * (m - 1) // 2, dtype=float)
mask = numpy.isfinite(data)
k = 0
for i in range(m - 1):
for j in range(i + 1, m):
curr = numpy.logical_and(mask[i], mask[j])
u = data[i][curr]
v = data[j][curr]
dm[k] = norm(u - v)
k += 1
10000次循环,最佳3:每个循环98.9 µs
因此,我认为前进的方法是在函数中对上述代码进行Cythonize。
问题答案:
- 实际上,使用这种现成的解决方案可能会更好:[https]( https://scikit-
- learn.org/stable/modules/generated/sklearn.metrics.pairwise.nan_euclidean_distances.html)
-
//scikit-
learn.org/stable/modules/generation/sklearn.metrics.pairwise.nan_euclidean_distances.html
但是,缺点似乎是在缺少值时应用权重更加棘手