Group Abstract Group Abstract

Message Boards Message Boards

0
|
5.5K Views
|
8 Replies
|
9 Total Likes
View groups...
Share
Share this post:

[?] Get the number of specified elements in a sparse array?

Posted 8 years ago

If myArray is a sparse array with some elements already explicitly defined. How can I find that number of specified elements? Those that do not have the default value. I.e. the number, which is displayed when I just say Print[myArray] ?

I know that

Length[ArrayRules[myArray]] - 1

works. But this seems pretty strange for me. Is there no standard function similar to Length?

POSTED BY: Werner Geiger
8 Replies

Actually I don't understand why your solution is faster, since myArray["NonzeroValues"] creates a list just like ArrayRules[myArray] does.

Mathematica employs the copy-on-write paradigm. When we do

a = Range[10000];

it does indeed allocate memory for 10000 elements. But when we do

b = a;

it does not allocate memory for a further 10000 elements. b and a will point to the same area of memory.

Conceptually, a and b are two entirely separate variables. But the system will take the opportunity to share storage between them when possible.

Now if we change b using

b[[1]] = 42;

then a and b won't have the same value anymore, and won't be able to share storage. Only at this point—i.e. when changing b—will Mathematica allocate separate storage for b.

It's also interesting to read up on the Share[] command, which will attempt to detect duplicate data and share their storage to conserve memory.

Most of this sharing is fully transparent to the user. We do not need to be aware of it to get correct results. But it is useful to know about it when we want to write efficient programs.

POSTED BY: Szabolcs Horvát
Posted 8 years ago

"Mathematica employs the copy-on-write paradigm."

Ja, I understand that. I wrote several compilers and interpreters myself.

Hence myArray["NonzeroValues"] does not create a copy of that list, since it has that list already in the internal structure of a sparse array. But ArrayRules[myArray] are not directly available and have to be constructed.

Ja, that sounds understandable.

Thank you for your comments. I learned a lot from them.

POSTED BY: Werner Geiger

What I should have made clearer: I do not think there is any other way than "NonzeroValues" to do what you are looking for (i.e. efficient access). I would be happy to be proven wrong though.

POSTED BY: Szabolcs Horvát
POSTED BY: Szabolcs Horvát
Posted 8 years ago
POSTED BY: Werner Geiger
Posted 8 years ago
POSTED BY: Werner Geiger
Posted 8 years ago
POSTED BY: Werner Geiger

There are two separate issues here:

  • How to get the number of explicitly stored elements efficiently? Use Length[myArray["NonzeroValues"]]. This is undocumented syntax, but it is widely used publicly and—in my opinion—very unlikely to go away in the future. See here. I expect this method to be the most efficient way (in speed and memory usage) to accomplish your task.

    Caveat: Despite its name, "NonzeroValues" returns non-default values even in the case when the default value is something else than zero.

  • How to get the number of elements that are different from the default value? This is a separate issue because some of the explicitly stored elements may be equal to the default value. To get rid of these, we must re-build the sparse array: Length[ SparseArray[myArray]["NonzeroValues"] ]

If you are curious to see a sparse array that has explicitly stored elements that are equal to the background value, here is an example:

In[25]:= sa = SparseArray[{0, 1, 2, 3}];

In[26]:= sa2 = If[# > 2, 0, #] & /@ sa;

In[27]:= sa2["NonzeroValues"]

Out[27]= {1, 2, 0}

In[28]:= ArrayRules[sa2]
Out[28]= {{2} -> 1, {3} -> 2, {4} -> 0, {_} -> 0}

In[29]:= sa3 = SparseArray[sa2]; (* rebuild the array *)

In[30]:= ArrayRules[sa3]
Out[30]= {{2} -> 1, {3} -> 2, {_} -> 0}
POSTED BY: Szabolcs Horvát
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard