Поэлементное деление разреженных матриц, игнорируя 0/0 - PullRequest
0 голосов
/ 25 мая 2018

У меня есть две разреженные матрицы E и D, которые имеют ненулевые записи в тех же местах.Теперь я хочу иметь E/D в качестве разреженной матрицы, определенной только в том случае, когда D не равен нулю.

Например, возьмем следующий код:

import numpy as np
import scipy

E_full = np.matrix([[1.4536000e-02, 0.0000000e+00, 0.0000000e+00, 1.7914321e+00, 2.6854320e-01, 4.1742600e-01, 0.0000000e+00],
                    [9.8659000e-03, 0.0000000e+00, 0.0000000e+00, 1.9106752e+00, 5.7283640e-01, 1.4840370e-01, 0.0000000e+00],
                    [1.3920000e-04, 0.0000000e+00, 0.0000000e+00, 9.4346500e-02, 2.8285900e-02, 4.3967800e-02, 0.0000000e+00],
                    [0.0000000e+00, 4.5182676e+00, 0.0000000e+00, 0.0000000e+00, 7.3000000e-06, 1.5100000e-05, 4.0746900e-02],
                    [0.0000000e+00, 0.0000000e+00, 3.4002088e+00, 4.6826200e-02, 0.0000000e+00, 2.4246900e-02, 3.4529236e+00]])
D_full = np.matrix([[0.36666667, 0.        , 0.        , 0.33333333, 0.2       , 0.1       , 0.        ],
                    [0.23333333, 0.        , 0.        , 0.33333333, 0.4       , 0.03333333, 0.        ],
                    [0.06666667, 0.        , 0.        , 0.33333333, 0.4       , 0.2       , 0.        ],
                    [0.        , 0.63636364, 0.        , 0.        , 0.04545455, 0.03030303, 0.28787879],
                    [0.        , 0.        , 0.33333333, 0.33333333, 0.        , 0.22222222, 0.11111111]])
E = scipy.sparse.dok_matrix(E_full)
D = scipy.sparse.dok_matrix(D_full)

Тогда деление E/D даетполная матрица.

matrix([[3.96436360e-02,            nan,            nan, 5.37429635e+00, 1.34271600e+00, 4.17426000e+00,            nan],
        [4.22824292e-02,            nan,            nan, 5.73202566e+00, 1.43209100e+00, 4.45211145e+00,            nan],
        [2.08799990e-03,            nan,            nan, 2.83039503e-01, 7.07147500e-02, 2.19839000e-01,            nan],
        [           nan, 7.10013476e+00,            nan,            nan, 1.60599984e-04, 4.98300005e-04, 1.41541862e-01],
        [           nan,            nan, 1.02006265e+01, 1.40478601e-01,            nan, 1.09111051e-01, 3.10763127e+01]])

Я также попробовал другой пакет.

import sparse
sparse.COO(E) / sparse.COO(D)

Это привело меня к ошибке.

ValueError: Performing this operation would produce a dense result: <ufunc 'true_divide'>

Итак, он пытается создатьплотная матрица.

Я так понимаю, это связано с тем, что 0/0 = nan.Но я все равно не интересуюсь этими ценностями.Так как я могу избежать их вычисления?

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Обновление : (вдохновлено sacul) Создайте пустой dok_matrix и измените только ненулевую часть D с nonzero.(Это должно работать и для разреженных матриц, кроме dok_matrix.)

F = scipy.sparse.dok_matrix(E.shape)
F[D.nonzero()] = E[D.nonzero()] / D[D.nonzero()]

Вы можете попробовать update + nonzero метод для dok_matrix.

nonzero_idx = [tuple(l) for l in np.transpose(D.nonzero())]
D.update({k: E[k]/D[k] for k in nonzero_idx})

Сначала мы используем nonzero, чтобы зафиксировать индексы в матрице D, которые не равны 0. Затем мы помещаем индексы в updateметод, в котором мы поставляем словарь

{k: E[k]/D[k] for k in nonzero_idx}

таким образом, что значения в D будут обновляться в соответствии с этим словарем.

Объяснение:

То, что делает D.update({k: E[k]/D[k] for k in nonzero_idx}),

for k in {k: E[k]/D[k] for k in nonzero_idx}.keys():
    D[k] = E[k]/D[k]

Обратите внимание, что это изменение D на месте.Если вы хотите создать новую разреженную матрицу вместо изменения D на месте, скопируйте D в другую матрицу, скажем ret.

nz = [tuple(l) for l in np.transpose(D.nonzero())]
ret = D.copy()
ret.update({k: E[k]/D[k] for k in nz})
0 голосов
/ 25 мая 2018

Не думаю, что это проблема того, что у вас есть nan значения, это ожидаемый результат.

Если вы хотите заменить nan на 0, вы можете использовать np.nan_to_num (doc: https://docs.scipy.org/doc/numpy/reference/generated/numpy.nan_to_num.html)

...