Reputation: 2511
When trying to directly set the data
attribute of a sparse lil_matrix
, I encounter very unexpected behavior. Can someone explain what is going on in the following simple example?
My particular use case is I want to set the row modulo 2; i.e. in dense-matrix-speak I just want to do matrix[0] %= 2
.
from scipy import sparse
import numpy as np
np.random.seed(0)
matrix = sparse.rand(10**3,10**3).tolil()
num_entries = len(matrix[0].data[0])
print num_entries
# 9
# this throws no errors...
matrix[0].data[0] = [2]*num_entries
# but does nothing!
assert (np.array(matrix[0].data) == 2).all() # FAILS
# in fact nothing can be done to alter .data directly...
matrix[0].data[0].pop() # returns the last float from the row
# but does not actually pop it from the row!
assert (len(matrix[0].data[0]) == num_entries-1) # FAILS
Upvotes: 1
Views: 226
Reputation: 2511
@vlsd found the bug, but I'm adding this to say more.
The issue with the code I posted is that I assign (throughout) to matrix[0].data
. The problem is that matrix[0]
doesn't work the same as dense-arrays; it's not simply pointing to the same object, but making a new object (I think). So assigning data to this new object is fine, but it just doesn't affect matrix
. That's the problem.
So the following code works fine:
matrix.data[0] = [2]*num_entries
assert (np.array(matrix.data[0]) == 2).all() # passes
matrix.data[0].pop()
assert (len(matrix.data[0]) == num_entries-1) # passes
NB That popping from the list is generally a bad idea as this probably ruins the integrity of the sparse-matrix. But this was just to demo. And it now makes sense.
Upvotes: 0
Reputation: 945
I'm not quite sure what kind of object matrix[0]
is, but I think you mean to drop the indexing on matrix
and only keep it on data
:
num_entries = len(matrix.data[0])
matrix.data[0] = [2]*num_entries
Upvotes: 1