Если я использую формат sparse.lil_matrix, как я могу легко и эффективно удалить столбец из матрицы?
Как я могу эффективно удалить столбец из разреженной матрицы?
Ответы (6)
Я сам этого хотел, и, по правде говоря, пока нет отличного встроенного способа сделать это. Вот как это сделать. Я решил создать подкласс 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)
Я пробовал, багов не вижу. Я, конечно, думаю, что это лучше, чем вырезать столбец, который, насколько мне известно, просто создает новую матрицу.
Я также решил сделать функцию removerow, но я не думаю, что она так же хороша, как removecol. Я ограничен тем, что не могу удалить одну строку из 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.
Гораздо проще и быстрее. Возможно, вам даже не понадобится преобразование в csr, но я точно знаю, что оно работает с разреженными матрицами csr, и преобразование между ними не должно быть проблемой.
from scipy import sparse
x_new = sparse.lil_matrix(sparse.csr_matrix(x)[:,col_list])
csc_matrix
.
- person silentser; 09.03.2017
Для разреженной матрицы 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.
Я новичок в python, поэтому мой ответ, вероятно, неверен, но мне было интересно, почему что-то вроде следующего не будет эффективным?
Допустим, ваша lil_matrix называется mat и вы хотите удалить i-й столбец:
mat=hstack( [ mat[:,0:i] , mat[:,i+1:] ] )
После этого матрица превратится в coo_matrix, но вы можете снова превратить ее в lil_matrix.
Хорошо, я понимаю, что это должно будет создать две матрицы внутри hstack, прежде чем он выполнит назначение переменной mat, так что это будет похоже на наличие исходной матрицы плюс еще одна одновременно, но я думаю, если разреженность достаточно велика тогда я думаю, что не должно быть проблем с памятью (поскольку память (и время) - это вся причина использования разреженных матриц).
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 в качестве входных данных - возможно, это будет кому-то полезно.
if min(col_list) = W.shape[1]:
во многих отношениях не имеет для меня никакого смысла. Во-первых, использование присваивания в аргументе if в Python является недопустимым синтаксисом. Во-вторых, почему вы проверяете мин. col_list с формой? Я думаю, что, может быть, вы хотели сделать if max(col_list) >= W.shape[1]:
? Конечно, это означает, что нельзя использовать и отрицательные индексы, и нет никаких проверок на индексы ниже 0 и что с ними делать.
- person Justin Peel; 03.06.2010
Глядя на примечания для каждой разреженной матрицы, особенно в нашем случае это матрица csc, она имеет следующие преимущества, перечисленные в документации [1]
- эффективные арифметические операции CSC+CSC, CSC*CSC и т.д.
- эффективная нарезка столбцов
- быстрые матричные векторные произведения (CSR, BSR могут быть быстрее)
Если у вас есть индексы столбцов, которые вы хотите удалить, просто используйте нарезку. Для удаления строк используйте матрицу csr, поскольку она эффективна при нарезке строк.