In numpy
reshape
означает изменить shape
таким образом, чтобы сохранить одинаковые числовые элементы.Таким образом, произведение терминов формы не может измениться.
Самый простой пример - это что-то вроде
np.arange(12).reshape(3,4)
Метод присваивания:
x = np.arange(12)
x.shape = (3,4)
method
(или np.reshape(...)
) возвращает новый массив.Назначение shape
работает на месте.
Примечание к документации, которое вы цитируете, вступает в игру, когда вы делаете что-то вроде
x = np.arange(12).reshape(3,4).T
x.reshape(3,4) # ok, but copy
x.shape = (3,4) # raises error
Чтобы лучше понять, что здесь происходит, распечатайте массив на разных этапах и посмотрите, как оригинал 0,1,2,...
смежные изменения.(это оставлено как упражнение для читателя, так как оно не является центральным в более широком вопросе.)
Существует функция и метод resize
, но он не используется много, и его поведение относительнодля просмотра и копирования сложно.
np.concatenate
(и варианты, такие как np.stack
, np.vstack
), создают новые массивы и копируют все данные из входных данных.
Список (и массив dtype объекта) содержит указатели на элементы (которые могут быть массивами) и поэтому не требуют копирования данных.
Разреженные матрицы хранят свои данные (и индексы строк / столбцов) в различных атрибутах, которые различаются междуформаты.coo
, csr
и csc
имеют 3 1d массива.lil
имеет 2 массива объектов, содержащих списки.dok
- это подкласс словаря.
lil_matrix
реализует метод reshape
.Других форматов нет.Как и в случае np.reshape
, произведение размеров не может измениться.
Теоретически разреженная матрица может быть «встроена» в большую матрицу с минимальным копированием данных, поскольку все новые значения будут использоваться по умолчанию.0 и не занимают места.Но детали этой операции не были разработаны ни для одного из форматов.
sparse.hstack
и sparse.vstack
(не используйте версии numpy
на разреженных матрицах) работают путем объединения coo
атрибуты входов (через sparse.bmat
).Так что да, они создают новые массивы (data
, row
, col
).
Минимальный пример создания более разреженной матрицы:
In [110]: M = sparse.random(5,5,.2,'coo')
In [111]: M
Out[111]:
<5x5 sparse matrix of type '<class 'numpy.float64'>'
with 5 stored elements in COOrdinate format>
In [112]: M.A
Out[112]:
array([[0. , 0.80957797, 0. , 0. , 0. ],
[0. , 0. , 0. , 0. , 0. ],
[0. , 0.23618044, 0. , 0.91625967, 0.8791744 ],
[0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0. , 0.7928235 , 0. ]])
In [113]: M1 = sparse.coo_matrix((M.data, (M.row, M.col)),shape=(7,5))
In [114]: M1
Out[114]:
<7x5 sparse matrix of type '<class 'numpy.float64'>'
with 5 stored elements in COOrdinate format>
In [115]: M1.A
Out[115]:
array([[0. , 0.80957797, 0. , 0. , 0. ],
[0. , 0. , 0. , 0. , 0. ],
[0. , 0.23618044, 0. , 0.91625967, 0.8791744 ],
[0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0. , 0.7928235 , 0. ],
[0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0. , 0. , 0. ]])
In [116]: id(M1.data)
Out[116]: 139883362735488
In [117]: id(M.data)
Out[117]: 139883362735488
M
иM1
имеют одинаковый атрибут data
(тот же идентификатор массива).Но большинство операций с этими матрицами потребует преобразования в другой формат (например, csr
для математики или lil
для изменения значений) и будет включать копирование и изменение атрибутов.Таким образом, эта связь между двумя матрицами будет нарушена.
Когда вы создаете разреженную матрицу с функцией, подобной coo_matrix
, и не предоставляете параметр shape
, она выводит форму из предоставленных координат,Если вы предоставляете shape
, он использует это.Эта форма должна быть как минимум такой же большой, как подразумеваемая форма.С помощью lil
(и dok
) вы можете выгодно создать «пустую» матрицу с большой формой, а затем задать значения итеративно.Вы не хотите делать это с csr
.И вы не можете напрямую установить значения coo
.
Канонический способ создания разреженных матриц - это создание массивов или списков data
, row
и col
итеративно из различных частей -составьте список добавлений / расширений или объединений массивов и создайте из него массив формата coo
(или csr
).Таким образом, вы делаете все «растущие» перед созданием матрицы.
изменение _shape
Создайте матрицу:
In [140]: M = (sparse.random(5,3,.4,'csr')*10).astype(int)
In [141]: M
Out[141]:
<5x3 sparse matrix of type '<class 'numpy.int64'>'
with 6 stored elements in Compressed Sparse Row format>
In [142]: M.A
Out[142]:
array([[0, 6, 7],
[0, 0, 6],
[1, 0, 5],
[0, 0, 0],
[0, 6, 0]])
In [144]: M[1,0] = 10
... SparseEfficiencyWarning)
In [145]: M.A
Out[145]:
array([[ 0, 6, 7],
[10, 0, 6],
[ 1, 0, 5],
[ 0, 0, 0],
[ 0, 6, 0]])
ваш новый метод формы (убедитесь, что dtype
из indptr
не изменяется):
In [146]: M._shape = (6,3)
In [147]: newptr = np.hstack((M.indptr,M.indptr[-1]))
In [148]: newptr
Out[148]: array([0, 2, 4, 6, 6, 7, 7], dtype=int32)
In [149]: M.indptr = newptr
In [150]: M
Out[150]:
<6x3 sparse matrix of type '<class 'numpy.int64'>'
with 7 stored elements in Compressed Sparse Row format>
In [151]: M.A
Out[151]:
array([[ 0, 6, 7],
[10, 0, 6],
[ 1, 0, 5],
[ 0, 0, 0],
[ 0, 6, 0],
[ 0, 0, 0]])
In [152]: M[5,2]=10
... SparseEfficiencyWarning)
In [153]: M.A
Out[153]:
array([[ 0, 6, 7],
[10, 0, 6],
[ 1, 0, 5],
[ 0, 0, 0],
[ 0, 6, 0],
[ 0, 0, 10]])
Добавление столбца также работает:
In [154]: M._shape = (6,4)
In [155]: M
Out[155]:
<6x4 sparse matrix of type '<class 'numpy.int64'>'
with 8 stored elements in Compressed Sparse Row format>
In [156]: M.A
Out[156]:
array([[ 0, 6, 7, 0],
[10, 0, 6, 0],
[ 1, 0, 5, 0],
[ 0, 0, 0, 0],
[ 0, 6, 0, 0],
[ 0, 0, 10, 0]])
In [157]: M[5,0]=10
.... SparseEfficiencyWarning)
In [158]: M[5,3]=10
.... SparseEfficiencyWarning)
In [159]: M
Out[159]:
<6x4 sparse matrix of type '<class 'numpy.int64'>'
with 10 stored elements in Compressed Sparse Row format>
In [160]: M.A
Out[160]:
array([[ 0, 6, 7, 0],
[10, 0, 6, 0],
[ 1, 0, 5, 0],
[ 0, 0, 0, 0],
[ 0, 6, 0, 0],
[10, 0, 10, 10]])
совместное использование атрибутов
Я могу сделатьновая матрица из существующей:
In [108]: M = (sparse.random(5,3,.4,'csr')*10).astype(int)
In [109]: newptr = np.hstack((M.indptr,6))
In [110]: M1 = sparse.csr_matrix((M.data, M.indices, newptr), shape=(6,3))
data
приписывает общую, по крайней мере, в смысле представления:
In [113]: M[0,1]=14
In [114]: M1[0,1]
Out[114]: 14
Но если я изменю M1
, добавив ненулевойзначение:
In [117]: M1[5,0]=10
...
SparseEfficiencyWarning)
Разрыв связи между матрицами:
In [120]: M[0,1]=3
In [121]: M1[0,1]
Out[121]: 14