Если я использую формат 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-матрица, так как она эффективна при сортировке строк