# Finding elements from a sparse matrix

I am dealing sparse matrices of very large dimensions. I need to locate the positive and negative elements of the matrices and make lists of their corresponding positions. Of course I can write a program which scans every element and gives the output. But is it possible to do it in a neater way? for instance, to make a list of 1's, I used Position[S,1], but in future I need to get a list of positions of all entries which are >0 for example.

As suggested, I am giving an example of one of the smallest lists. For instance, I want to make a list of positions of elements which are >0.

S={{1,0,0,0,1,0,0,0,0,-1,0,0,0,-1,0,0,0,-1,0,0,0,0,-1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{1,0,0,0,2,0,0,0,0,-1,0,0,0,-1,0,0,0,-1,0,0,0,0,-1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{-1,0,0,0,-1,0,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,0,-1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{-1,0,0,0,-1,0,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,0,-1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{-1,0,0,0,-1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,-1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{-1,0,0,0,-1,0,0,0,0,-1,0,0,0,-1,0,0,0,-1,1,0,0,0,2,0,0,0,1},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1}};
-
@Öskå I have added one small example of $S$. – RSG Mar 13 '14 at 11:27
Related: (31908), (37691), (19910) – Mr.Wizard Mar 13 '14 at 13:03

Take a look at Unitize, UnitStep, Clip, Sign, etc. and the NonzeroPositions property of sparse arrays. Using these in combination with appropriate arithmetic operations you can quickly get positions.

You could also take a look at FilterRules, and use this against the array rules to get positions for specified elements.

With your updated post, e.g., elements >0:

SparseArray[UnitStep[Sign[S] - 1]]["NonzeroPositions"]

(*
{{1, 1}, {1, 5}, {5, 1}, {5, 5}, {10, 10}, {10, 14}, {10, 18}, {14,
10}, {14, 14}, {14, 18}, {18, 10}, {18, 14}, {18, 18}, {19,
19}, {19, 23}, {19, 27}, {23, 19}, {23, 23}, {23, 27}, {27,
19}, {27, 23}, {27, 27}}
*)

Using FilterRules:

FilterRules[Reverse /@ ArrayRules[S], ele_ /; ele > 0][[All, 2]]

(*
{{1, 1}, {1, 5}, {5, 1}, {5, 5}, {10, 10}, {10, 14}, {10, 18}, {14,
10}, {14, 14}, {14, 18}, {18, 10}, {18, 14}, {18, 18}, {19,
19}, {19, 23}, {19, 27}, {23, 19}, {23, 23}, {23, 27}, {27,
19}, {27, 23}, {27, 27}}
*)

If you're going to be doing various such searches on a given array, get the reversed rules once and use that result in the FilterRules to save time.

-
nice and concise +1 – ubpdqn Mar 13 '14 at 11:39

This is reasonably fast and straightforward:

SparseArray[Positive@S, Automatic, False]["NonzeroPositions"]

Update: Hmm, this slight modification of rasher's method is even faster on regular arrays:

SparseArray[1 - UnitStep[-S]]["NonzeroPositions"]

Timing comparison. The array is about 90% zeros, 5% positive, 5% negative.

Table[
foo = RandomChoice[{0.9, 0.05, 0.05} -> {0, -2, 2}, {10^k, 100}];
{SparseArray[UnitStep[Sign[foo] - 1]]["NonzeroPositions"]        // timeAvg,
SparseArray[Positive@foo, Automatic, False]["NonzeroPositions"] // timeAvg,
SparseArray[1 - UnitStep[-foo]]["NonzeroPositions"]             // timeAvg},
{k, 3, 6}
] ~Prepend~ {"Sign", "Positive", "-foo"} // Grid

If foo or S is already a SparseArray, then rasher's Sign method is a bit faster than Positive. Oddly, the "-foo" method is now slowest.

Table[
foo = SparseArray[
RandomChoice[{0.9, 0.05, 0.05} -> {0, -2, 2}, {10^k, 100}]];
{SparseArray[UnitStep[Sign[foo] - 1]]["NonzeroPositions"]        // timeAvg,
SparseArray[Positive@foo, Automatic, False]["NonzeroPositions"] // timeAvg,
SparseArray[1 - UnitStep[-foo]]["NonzeroPositions"]             // timeAvg}},
{k, 3, 6}
] ~Prepend~ {"Sign", "Positive", "-foo"} // Grid

The timing function goes back to stackoverflow and Timo and Mr.Wizard.

SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] :=
Do[If[# > 0.3, Return[#/5^i]] & @@  AbsoluteTiming@Do[func, {5^i}], {i, 0, 15}];
-
Thanks for timing and analysis! +1 – ciao Mar 13 '14 at 21:20
@MichaelE2 ...very instructive...thanks +1 – ubpdqn Mar 15 '14 at 15:46

Here is an example that uses properties of SparseArray. A small test array is used to illustrate. positive gives the positions of positive values in the sparse array and negative gives the positions of the negative values in the sparse array. These can be sa = extracts using Extract[sa,positive] etc.

SparseArray[