6
$\begingroup$

given a SparseArray

s = SparseArray[{1, 10} -> 1, {1, 10}, a]

I can extract the background value (see What are SparseArray Properties? How and when should they be used? )

s["Background"]

a

but is there a direct way to change it? We can of course convert to Normal form and create a new SparseArray

SparseArray[Normal[s] /. a -> b, Dimensions[s], b]

but note this will also change values that are explicitly a , and is undesirable in case the array is really big and really sparse then passing through the normal form is unwieldy.

Best I've come up with is to do FullForm and manually edit the third argument..

come up with an answer this, you can also answer this: Why does WeightedAdjacencyMatrix take the weight for absent edges to be zero?

$\endgroup$
  • 3
    $\begingroup$ How about s1 = ArrayRules[s] /. s["Background"] -> newBackground // SparseArray? $\endgroup$ – corey979 Nov 22 '16 at 23:02
  • $\begingroup$ I gave an answer below but it occurred to me that this might be quite version dependent since somewhere between v7 that I am using and the latest one SparseArray objects where changed to atomic expressions I think.. $\endgroup$ – Kiro Nov 23 '16 at 6:51
  • $\begingroup$ Did you notice that MatrixPlot doesn't work correctly if the background element is not zero? $\endgroup$ – Szabolcs Nov 23 '16 at 10:57
  • $\begingroup$ Just wanted to note that LibraryLink provides a low-level interface to sparse arrays, but it has no way of changing the background value the way you want to. Changing the implicit value triggers a recomputation of explicit positions. Probably the only way is to construct a new sparse array from the explicit positions (the straightforward way). $\endgroup$ – Szabolcs Nov 23 '16 at 10:58
  • $\begingroup$ george, I notice that you did not Accept my answer. That's your prerogative of course, but may I know your reason? I believe my method does what you requested. Have you found a problem with it? $\endgroup$ – Mr.Wizard Jun 11 '17 at 11:52
7
$\begingroup$

You can change the background using replacement; here making the background "x":

s = SparseArray[{1, 10} -> 1, {1, 10}, a]

s /. (sa : SparseArray)[a_, b_, background_, d_] :> sa[a, b, "x", d]

enter image description here

$\endgroup$
  • $\begingroup$ not sure this is a safe method? In your example change background value to 1 and then back to 0.... Setting the background value will remove the elements with the same value (which is the purpose), however, changing the background value again does not bring the original element values back ... $\endgroup$ – Sander Mar 15 at 9:30
  • $\begingroup$ @Sander I don't think I understand your concern. Would you try explaining it for me again? The original background element in my example is a not 0. Perhaps we have a Symbol name collision here; if you use "a" (string) for the original background and second replacement does it behave as you expect? $\endgroup$ – Mr.Wizard Mar 15 at 14:02
  • $\begingroup$ I implicitly assumed here that the relevance of setting a background value was minimizing the number of elements. Therefore changing (I mean changing, not defining during creation of SparseArray) the background value should not change the actual matrix. It does ... e.g. SparseArray[{1,10}->1,{1,10},0]]/.(sa:SparseArray)[a_,b_,background_,d_]:>sa[a,b,1,d] $\endgroup$ – Sander Mar 16 at 1:57
  • $\begingroup$ @Sander That would be an entirely different Question. This one is about replacing the background value, e.g. /. a -> b in the Question code. For what you apparently want you can reform the SparseArray like this: SparseArray[s, Automatic, 1] $\endgroup$ – Mr.Wizard Mar 16 at 6:50
  • $\begingroup$ I misread the question, you are right. But I am happy I asked as your response helped me ... so to optimize the count of elements in a SparseArray where the most common element is not known ahead of time, this is the way to go: SparseArray[a, Automatic, MaximalBy[Tally[Flatten[a]], Last]] $\endgroup$ – Sander Mar 16 at 7:13
4
$\begingroup$
s = SparseArray[{1, 10} -> 1, {1, 10}, a];
s2 = SparseArray[s["NonzeroPositions"] -> s["NonzeroValues"], Dimensions[s], b];

A slightly slower way using ArrayRules:

s3 = SparseArray[Most@ArrayRules[s], Dimensions[s], b];

I haven't tested these on later versions.

$\endgroup$
  • 1
    $\begingroup$ Remove the Thread to make it more efficient. Also maybe remove the part of the post that doesn't answer the question? +1 $\endgroup$ – Szabolcs Nov 23 '16 at 11:01
  • $\begingroup$ @Szabolcs Thanks for the tip! $\endgroup$ – Kiro Nov 23 '16 at 11:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.