我对于
出于谨慎起见,让我们先排除矩阵维度的错误。根据文档:
“点通过矩阵X中的m个n维行向量来安排。”
因此,让我们在10维空间中生成三个带有缺失值的点:
如果我计算这三个观测值的欧几里得距离:
我得到了如下结果:
编辑:
由于我的完整矩阵相当大,因此我对此处提供的小数据集进行了一些计时测试。
1.) 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")
我得到的结果是:
array([ nan, nan, nan])
然而,如果我筛选掉所有含有缺失值的列,我确实可以获得正确的距离值:
valid = [i for (i, col) in enumerate(data.T) if ~numpy.isnan(col).any()]
pdist(data[:, valid], "euclidean")
我得到了如下结果:
array([ 3.35518662, 2.35481185, 3.10323893])这种方法会浪费更多的数据,因为我不需要过滤整个矩阵,只需要处理一次比较的向量对。我能否使pdist或类似函数执行成对掩码处理呢?
编辑:
由于我的完整矩阵相当大,因此我对此处提供的小数据集进行了一些计时测试。
1.) Scipy函数。
%timeit pdist(data, "euclidean")
每个循环24.4微秒,3次中的最佳结果为10000个循环。
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微秒。
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
3次循环中的最佳10000次迭代时间为98.9微秒
因此,我认为前进的方法是将上述代码封装在一个函数中进行Cython化。
ma.array
的掩码,对吧?也许您可以编辑您的答案或者我们聊一下。 - Midnighter