7
$\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$
4
  • 3
    $\begingroup$ How about s1 = ArrayRules[s] /. s["Background"] -> newBackground // SparseArray? $\endgroup$
    – corey979
    Nov 22, 2016 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, 2016 at 6:51
  • 1
    $\begingroup$ Did you notice that MatrixPlot doesn't work correctly if the background element is not zero? $\endgroup$
    – Szabolcs
    Nov 23, 2016 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, 2016 at 10:58

2 Answers 2

8
$\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$
5
  • $\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, 2019 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, 2019 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, 2019 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, 2019 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, 2019 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$
2
  • 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, 2016 at 11:01
  • $\begingroup$ @Szabolcs Thanks for the tip! $\endgroup$
    – Kiro
    Nov 23, 2016 at 11:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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