2
$\begingroup$

This question already has an answer here:

Often I need to use same matrix several times and for that I save them in an external file. Converting the matrix into SparseArray can save a lot of space in this process.

For example consider this SparseArray.

spdat = Join[RandomInteger[{1, 10}, 2], {RandomReal[]}] & /@ Range[20];
spmat = SparseArray[(#[[1 ;; 2]] -> #[[3]]) & /@ spdat, {10, 10}]

Lets consider this spdat

{{9, 10, 0.11555}, {5, 8, 0.0436915}, {6, 2, 0.376473}, {7, 10, 0.893704}, {6, 3, 0.114267}, {2, 1, 0.860136}, {10, 7, 0.462883}, {5, 5, 0.126532}, {9, 8, 0.327185}, {10, 3, 0.36935}, {1, 8, 0.98363}, {3, 3, 0.864916}, {1, 1, 0.523974}, {1, 8, 0.752075}, {7, 1, 0.0122767}, {10, 4, 0.872767}, {4, 7, 0.555469}, {1, 4, 0.395135}, {7, 8, 0.842624}, {7, 4, 0.943731}}

If I can Export this as a data file, I can create my SparseArray from that. A simple Export will export the whole matrix in dense form which will create a huge file.

If I check the InputForm of spmat, it returns,

InputForm[spmat]

SparseArray[Automatic, {10, 10}, 0, {1, {{0, 3, 4, 5, 6, 8, 10, 14, 14, 16, 19}, {{1}, {4}, {8}, {1}, {3}, {7}, {5}, {8}, {2}, {3}, {1}, {4}, {8}, {10}, {8}, {10}, {3}, {4}, {7}}}, {0.5239738483968632, 0.3951345317083965, 0.9836297206953681, 0.8601364789360151, 0.8649158619094384, 0.5554690352192444, 0.12653163124345568, 0.04369153890486932, 0.3764726821240931, 0.11426712799092975, 0.012276677822715243, 0.9437312355928948, 0.8426237324241401, 0.8937036888680452, 0.32718527756860794, 0.11555023823345034, 0.36934965959862076, 0.872767483243448, 0.4628830528072616}}]

How can I retrieve spdat from this? Definitely the third argument contains the information about the position of nonzero elements, but I can't recognise them!

$\endgroup$

marked as duplicate by m_goldberg, dr.blochwave, Oleksandr R., Öskå, ilian Sep 13 '15 at 18:04

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 5
    $\begingroup$ The easiest thing to do is probably to Export the sparse array as .m or .mx file, then you can simply Import it back without thinking what its pieces mean. The .mx file has an additional advantage that it will keep packed arrays packed. If you do want to understand the anatomy of sparse arrays, you can read e.g. this discussion. $\endgroup$ – Leonid Shifrin Sep 11 '15 at 13:37
  • 1
    $\begingroup$ @LeonidShifrin is almost certainly right, but if really want spdat back you can do something like MapThread[Append, {#["NonzeroPositions"], #["NonzeroValues"]}] &@spmat $\endgroup$ – chuy Sep 11 '15 at 13:45
  • $\begingroup$ The only thing I'll add to @LeonidShifrin's comment is that while the .mx format is great, it is not portable across different OS's or across different versions of MMA. I use it all the time, but this is important to keep in mind. $\endgroup$ – march Sep 11 '15 at 15:24
  • $\begingroup$ @march Since V10, .mx is portable across OS - but not architectures, and perhaps may not also be across different versions of Mathematica. $\endgroup$ – Leonid Shifrin Sep 11 '15 at 15:28
  • $\begingroup$ @LeonidShifrin. Apparently the documentation hasn't been updated, then! Both online and in my version of V10, the help files say that .mx was updated last at V6 and gives the caveats I gave above. $\endgroup$ – march Sep 11 '15 at 15:58
2
$\begingroup$

Here are two different ways of getting spdat from spmat:

Join[#[[1]], {#[[2]]}] & /@ (ArrayRules[spmat])

or (this is chuy's suggestion)

MapThread[Append, {#["NonzeroPositions"], #["NonzeroValues"]}] &@spmat
$\endgroup$
4
$\begingroup$

Using Export directly "just works":

In[23]:= mat = SparseArray[DiagonalMatrix[2^Range[0, 10]]];

In[24]:= file = Export[CreateTemporary[], mat, "Package"];

In[25]:= FilePrint[file]

During evaluation of In[25]:=
(* Created with the Wolfram Language : www.wolfram.com *)
SparseArray[Automatic, {11, 11}, 0, 
 {1, {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, {{1}, {2}, {3}, {4}, {5}, {6}, 
   {7}, {8}, {9}, {10}, {11}}}, {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 
  1024}}]

In[26]:= DeleteFile[file]
$\endgroup$
2
$\begingroup$

Your sample spdat generated from random numbers is of course likely to be just an example for this question, but nonetheless in the interest of thoroughness I would like to point that in the literal case you cannot be sure to recover your spdat from spmat, because your spdat may contain duplicate directives, only one of which is retained when you generate the SparseArray.

In the example spdat you post, for instance, there are two conflicting directives for position {1, 8} in the resulting matrix:

spdat = {{9, 10, 0.11555}, {5, 8, 0.0436915}, {6, 2, 0.376473}, {7, 10, 0.893704},
  {6, 3, 0.114267}, {2, 1, 0.860136}, {10, 7, 0.462883}, {5, 5, 0.126532},
  {9, 8, 0.327185}, {10, 3, 0.36935}, 

  {1, 8, 0.98363}, (*duplicated directive*)

  {3, 3, 0.864916}, {1, 1, 0.523974}, 

  {1, 8, 0.752075}, (*duplicated directive*)

  {7, 1, 0.0122767}, {10, 4, 0.872767}, {4, 7, 0.555469}, {1, 4, 0.395135},
  {7, 8, 0.842624}, {7, 4, 0.943731}}

Of course, the value corresponding to one of those two directives is lost in the generation of the SparseArray:

spmat = SparseArray[(#[[1 ;; 2]] -> #[[3]]) & /@ spdat, {10, 10}];
Join[#[[1]], {#[[2]]}] & /@ (ArrayRules[spmat]);

% == spdat
(*False*)

spmat[[1, 8]]
(* 0.98363, i.e. the first value encountered in your list of rules *)
$\endgroup$
  • $\begingroup$ Thanks @MarcoB. You are right. I just want to give an example. Right way to do that would be create the positions first with Union and then assign the values. I am just too lazy for that :) $\endgroup$ – Sumit Sep 12 '15 at 12:06
  • $\begingroup$ @Sumit Hehe, yes of course it was just an example, but I just wanted the caveat on the record for future readers :-) $\endgroup$ – MarcoB Sep 12 '15 at 15:30

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