Я немного озадачен тем, как _1 _ обрабатывает отсутствующие (nan
) значения.
Так что на случай, если я испортил размеры своей матрицы, давайте разберемся с этим. Из документов:
Точки расположены как m n-мерных векторов-строк в матрице X.
Итак, давайте сгенерируем три точки в 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")
10000 loops, best of 3: 24.4 µs per loop
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 loops, best of 3: 231 µs per loop
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 loops, best of 3: 98.9 µs per loop
Итак, я думаю, что путь вперед - это Cythonize приведенный выше код в функции.
ma.array
, если вы хотите скрыть данные, верно? Может быть, вы могли бы отредактировать свой ответ или мы немного поговорим. - person Midnighter   schedule 17.07.2014