Как эффективно удалить столбец из разреженной матрицы? - PullRequest
14 голосов
/ 03 марта 2010

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

Ответы [ 6 ]

10 голосов
/ 20 июня 2013

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

from scipy import sparse

x_new = sparse.lil_matrix(sparse.csr_matrix(x)[:,col_list])
7 голосов
/ 03 марта 2010

Я сам этого хотел, и, по правде говоря, пока нет отличного встроенного способа сделать это. Вот способ сделать это. Я решил сделать подкласс lil_matrix и добавить функцию remove_col. Если хотите, вы можете вместо этого добавить функцию removecol в класс 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)

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

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

    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.

4 голосов
/ 29 июня 2015

Для разреженной матрицы csr (X) и списка индексов, которые нужно отбросить (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.

2 голосов
/ 31 мая 2012

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

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

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

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

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

0 голосов
/ 26 декабря 2016

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

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

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

0 голосов
/ 03 июня 2010

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 в качестве входных данных - возможно, это будет кому-то полезно.

...