Нарезка разреженных матриц в Scipy - Какие типы работают лучше всего?
Учебник SciPy Sparse Matrix очень хорош, но на самом деле он выходит из раздела, посвященного разрезанию un (der), разработанному (все еще в виде контура) - см. раздел: "Обработка разреженных матриц" ).
Я попытаюсь обновить учебник, после ответа на этот вопрос.
У меня большая разреженная матрица - в настоящее время в формате dok_matrix.
import numpy as np
from scipy import sparse
M = sparse.dok_matrix((10**6, 10**6))
Для разных методов я хочу иметь возможность разрезать столбцы, а для других - срезать строки. В идеале я бы использовал расширенную индексацию (т.е. Логический вектор, bool_vect
), с помощью которого разрезать разреженную матрицу M
- как в:
bool_vect = np.arange(10**6)%2 # every even index
out = M[bool_vect,:] # Want to select every even row
или
out = M[:,bool_vect] # Want to select every even column
Во-первых, dok_matrices не поддерживают это, но я думаю, что он работает (медленно), если я сначала передаю lil_matrices, через sparse.lil_matrix(M)
Насколько я могу собрать из учебника - для среза столбцов я хочу использовать CSC и срезать строки, я хочу обрезать CSR. Значит, это означает, что я должен отливать матрицу M
с помощью:
M.tocsc()[:,bool_vect]
или
M.tocsr()[bool_vect,:]
Я догадываюсь здесь, и мой код медленный из-за этого. Любая помощь от кого-то, кто понимает, как это работает, будет оценена по достоинству. Спасибо заранее.
Если окажется, что я не должен индексировать мою матрицу с булевым массивом, а скорее список целых чисел (индексов) - это тоже то, что я с удовольствием узнаю. Какой бы ни был эффективнее.
Наконец - это большая матрица, поэтому бонусные очки, если это может произойти на месте/с трансляцией.
Ответы
Ответ 1
Хорошо, поэтому я уверен, что "правильный" способ сделать это:
если вы нарезаете столбцы, используйте tocsc() и срез, используя список/массив целых чисел. Булевы векторы, похоже, не делают трюк с разреженными матрицами - как это происходит с ndarrays в numpy. Это означает, что ответ есть.
indices = np.where(bool_vect)[0]
out1 = M.tocsc()[:,indices]
out2 = M.tocsr()[indices,:]
Но вопрос: это лучший способ? Это на месте?
На практике это, похоже, происходит на месте - и это намного быстрее, чем предыдущие попытки (используя lil_matrix).