Как можно эффективно удалить столбец из разреженной матрицы?

Если я использую формат sparse.lil_matrix, как можно легко и эффективно удалить столбец из матрицы?

Ответ 1

Я сам этого хотел, и, по правде говоря, еще нет встроенного способа сделать это. Вот способ сделать это. Я решил создать подкласс lil_matrix и добавить функцию remove_col. Если вы хотите, вместо этого вы можете добавить функцию removeecol в класс lil_matrix в вашем файле lib/site-packages/scipy/sparse/lil.py. Здесь код:

from scipy import sparse
from bisect import bisect_left

class lil2(sparse.lil_matrix):
    def removecol(self,j):
        if j < 0:
            j += self.shape[1]

        if j < 0 or j >= self.shape[1]:
            raise IndexError('column index out of bounds')

        rows = self.rows
        data = self.data
        for i in xrange(self.shape[0]):
            pos = bisect_left(rows[i], j)
            if pos == len(rows[i]):
                continue
            elif rows[i][pos] == j:
                rows[i].pop(pos)
                data[i].pop(pos)
                if pos == len(rows[i]):
                    continue
            for pos2 in xrange(pos,len(rows[i])):
                rows[i][pos2] -= 1

        self._shape = (self._shape[0],self._shape[1]-1)

Я пробовал и не вижу ошибок. Я, конечно, думаю, что это лучше, чем нарезать колонку, которая, как я знаю, просто создает новую матрицу.

Я также решил сделать функцию removerow, но я не думаю, что это так же хорошо, как удаление. Я ограничен тем, что не смог удалить одну строку из ndarray так, как хотелось бы. Здесь removerow, который может быть добавлен в класс выше

    def removerow(self,i):
        if i < 0:
            i += self.shape[0]

        if i < 0 or i >= self.shape[0]:
            raise IndexError('row index out of bounds')

        self.rows = numpy.delete(self.rows,i,0)
        self.data = numpy.delete(self.data,i,0)
        self._shape = (self._shape[0]-1,self.shape[1])

Возможно, я должен отправить эти функции в репозиторий Scipy.

Ответ 2

Гораздо проще и быстрее. Возможно, вам даже не понадобится преобразование в csr, но я точно знаю, что он работает с разреженными матрицами csr, и преобразование между ними не должно быть проблемой.

from scipy import sparse

x_new = sparse.lil_matrix(sparse.csr_matrix(x)[:,col_list])

Ответ 3

Я новичок в python, поэтому мой ответ, вероятно, неверен, но мне было интересно, почему что-то вроде следующего не будет эффективным?

Предположим, что ваша lil_matrix называется mat и вы хотите удалить i-й столбец:

mat=hstack( [ mat[:,0:i] , mat[:,i+1:] ] )

Теперь после этого матрица превратится в coo_matrix, но вы можете вернуть ее обратно в lil_matrix.

Хорошо, я понимаю, что это должно будет создать две матрицы внутри hstack, прежде чем он будет присваивать переменной mat, так что это будет похоже на оригинальную матрицу плюс еще одну в одно и то же время, но я думаю, если разреженность достаточно велика, поэтому я думаю, что проблем с памятью не должно быть (поскольку память (и время) является всей причиной использования разреженных матриц).

Ответ 4

Для разреженной матрицы csr (X) и списка индексов для drop (index_to_drop):

to_keep = list(set(xrange(X.shape[1]))-set(index_to_drop))    
new_X = X[:,to_keep]

Легко преобразовать lil_matrices в csr_matrices. Проверьте tocsr() в документация lil_matrix

Обратите внимание, что переход от csr к lil-матрицам с использованием tolil() стоит дорого. Таким образом, этот выбор хорош, когда вам не требуется иметь матрицу в формате lil.

Ответ 5


def removecols(W, col_list):
        if min(col_list) = W.shape[1]:
                raise IndexError('column index out of bounds')
        rows = W.rows
        data = W.data
        for i in xrange(M.shape[0]):
            for j in col_list:
                pos = bisect_left(rows[i], j)
                if pos == len(rows[i]):
                        continue
                elif rows[i][pos] == j:
                        rows[i].pop(pos)
                        data[i].pop(pos)
                        if pos == len(rows[i]):
                                continue
                for pos2 in xrange(pos,len(rows[i])):
                        rows[i][pos2] -= 1
        W._shape = (W._shape[0], W._shape[1]-len(col_list))
        return W

Просто переписал свой код для работы с col_list в качестве ввода - возможно, это будет полезно для кого-то.

Ответ 6

Рассматривая заметки для каждой разреженной матрицы, в частности, в нашем случае это csc-матрица, она имеет следующие преимущества, перечисленные в документации [1]

  • эффективные арифметические операции CSC + CSC, CSC * CSC и т.д.
  • эффективная сортировка столбцов
  • быстрые матричные векторные продукты (CSR, BSR может быть быстрее)

Если у вас есть индексы столбцов, которые вы хотите удалить, просто используйте нарезку. Для удаления строк используется csr-матрица, так как она эффективна при сортировке строк