It seems that Map
ing a function over a SparseArray
can produce a result where one of the explicit values in the array is the same as the background value. It seems to me that this is a bug because other functions appear to assume that an explicit value will never be the same as the background value.
Example
Let us create a sparse array,
In[1]:= sa = SparseArray[{1, 0, 2, 0, 3}];
and check its explicit values.
In[2]:= sa["NonzeroValues"]
Out[2]= {1, 2, 3}
Let us now change the first element (which is nonzero) to have the background value.
In[3]:= sa[[1]] = 0;
And check explicit values again:
In[4]:= sa["NonzeroValues"]
Out[4]= {2, 3}
As you can see, the sparse array has been recomputed so that none of the explicit values is 0. It is in a consistent state. This is what I expected.
Now let us modify elements in a different manner. Let us map a function over the sparse array in such a way that it will transform some of the explicit values to zero:
In[5]:= sa = SparseArray[{1, 0, 2, 0, 3}];
In[6]:= sa2 = Map[If[# > 2, 0, #] &, sa];
Check explicit values in the result:
In[7]:= sa2["NonzeroValues"]
Out[7]= {1, 2, 0}
Oops! What is that 0
doing in the list? Is should have been removed from the explicit values list.
Is this a bug? Do decide, let us take a look at how other functions handle this sparse array.
ArrayRules
works on both sparse and dense arrays. ArrayRules[arr, b]
gives the positions of elements that are different from b
. It works fine even if b
is different from the background element of a sparse arr
.
But here ArrayRules
fails to give the result I expect, even though the second element was given explicitly:
In[8]:= ArrayRules[sa2, 0]
Out[8]= {{1} -> 1, {3} -> 2, {5} -> 0, {_} -> 0}
That {5} -> 0
should not be in the list.
See how ArrayRules works if the default element is set to 1
. There is no problem this time:
In[9]:= ArrayRules[sa2, 1]
Out[9]= {{2} -> 0, {3} -> 2, {4} -> 0, {5} -> 0, {_} -> 1}
This suggests that either ArrayRules
or SparseArray
is misbehaving here. Which one should be considered the buggy one?
Does this SparseArray
have a broken internal state? Or does ArrayRules
fail to take a special case into account?
This array can be fixed using SparseArray[sa2]
.