8
$\begingroup$

I have a matrix:

enter image description here

I would like to sum all the first non-zero elements of each row so that I get a value of

$$25.5317 + 8.85471 + 6.90018 + 32.9436 + ... $$

and so on and simply ignore zero rows.

Similarly I would like to do the same again for the second non-zero elements from each row so that I get:

$$29.1235 + 11.0472 + 41.2639$$

$\endgroup$

4 Answers 4

8
$\begingroup$
 tbl = RandomChoice[{.5, .1, .05, .05, .05, .05, .05, .05, .05, .05} -> Range[0, 9], {10, 10}]; tbl//TableForm 

enter image description here

Remove all zeros from tbl and add zeros to the right to make a full array:

PadRight[tbl /. (0) -> Sequence[], Automatic] // TableForm 

enter image description here

Then sum each column:

 Tr /@ (Transpose@PadRight[tbl /. (0) -> Sequence[], Automatic]) (* {55, 59, 36, 28, 38, 14, 9} *) 

Update: To get a matrix with dimensions {nrows, ncolumns} from PadRight change Automatic to {nrows, ncolumns}. So,

 Tr /@ (Transpose@PadRight[tbl /. (0) -> Sequence[], {10,10}]) (* {55, 59, 36, 28, 38, 14, 9, 0 ,0, 0} *) 
$\endgroup$
2
  • $\begingroup$ Hi @kguler, seems to work but I originally had 5 columns, now after sorting, it is 4 columns? Why is that? I need to maintain the column to be constant. $\endgroup$ Commented Nov 16, 2012 at 2:27
  • 1
    $\begingroup$ @sebastian, to get a matrix with dimensions {nrows, ncolumns} from PadRight change Automatic to {nrows, ncolumns}. (The setting Automatic adds as many columns as needed to remove raggedness.) $\endgroup$ Commented Nov 16, 2012 at 2:37
6
$\begingroup$

Not as nice as the method given by kguler. Nevertheless, as an alternative:

myarray = {{0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 25.5317, 29.1235}, {0., 0., 0., 0., 8.85471}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 6.90018}, {0., 0., 0., 0., 32.9436}, {0., 0., 0., 0., 29.1235}, {0., 0., 0., 2.47854, 11.0472}, {0., 0., 16.1408, 41.2639, 45.7614}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}} 

(Using Flatten to transpose a ragged array):

Flatten[Select[#, FreeQ[#, 0. | 0] &] & /@ myarray, {2}] 

=>

{{25.5317, 8.85471, 6.90018, 32.9436, 29.1235, 2.47854, 16.1408}, {29.1235, 11.0472, 41.2639}, {45.7614}}

Therefore,

Total /@ Flatten[Select[#, FreeQ[#, 0. | 0] &] & /@ myarray, {2}] 

=>

{121.973, 81.4346, 45.7614}

Comparing with kguler's method

tbl = RandomChoice[{.5, .1, .05, .05, .05, .05, .05, .05, .05, .05} -> Range[0, 9], {10, 10}]; Tr /@ (Transpose@PadRight[tbl /. (0) -> Sequence[], Automatic]) == Total /@ Flatten[Select[#, FreeQ[#, 0. | 0] &] & /@ tbl, {2}] 

=>

True

Edit

Better, perhaps, is

Total /@ Flatten[DeleteCases[myarray, 0 | 0., 2], {2}] 

However, the best variation on the Flatten approach, I recon, is given below (as a comment) by rm -rf:

Total[Flatten[# /. 0 | 0. -> Sequence[], {2}], {2}] &@myarray 

=>

{121.973, 81.4346, 45.7614}

$\endgroup$
3
  • 1
    $\begingroup$ I was about to write an answer with this same approach. It can also be written as: Total[Flatten[# /. 0|0. -> Sequence[], {2}], {2}]& $\endgroup$ Commented Nov 15, 2012 at 18:42
  • $\begingroup$ @rm -rf. That is a nice one! Thanks. $\endgroup$ Commented Nov 15, 2012 at 19:52
  • $\begingroup$ Tom and @rm-rf, actually I like your method better:). $\endgroup$ Commented Nov 16, 2012 at 3:12
3
$\begingroup$

One can search for the first nonzero element in each row using Cases. Generate a random table:

m = Normal@SparseArray[ Thread@{RandomInteger[{1, 12}, 14], RandomInteger[{1, 6}, 14]} :> RandomReal[], {12, 6}]; 

Mathematica graphics

and pick the first match in each row:

Flatten[Cases[#, _?(! PossibleZeroQ@# &), 1, 1] & /@ m] 

Or extending the Sequence replacement method in kguler's answer:

m /. {0 | 0. -> Sequence[]} /. {} -> Sequence[] /. {x_?NumberQ, ___} :> x 
{0.252222, 0.998427, 0.0562231, 0.849365, 0.582891, 0.0896831, 0.31189, 0.524075} 

To get the second nonzero element from each row:

m /. {0 | 0. -> Sequence[]} /. {} | {_} -> Sequence[] /. {_?NumberQ, x_, ___} :> x 
{0.949761, 0.841579, 0.0275406, 0.500705} 

Total then does the summing.

$\endgroup$
3
$\begingroup$

Using 1066's data

mat = {{0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 25.5317, 29.1235}, {0., 0., 0., 0., 8.85471}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 6.90018}, {0., 0., 0., 0., 32.9436}, {0., 0., 0., 0., 29.1235}, {0., 0., 0., 2.47854, 11.0472}, {0., 0., 16.1408, 41.2639, 45.7614}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}, {0., 0., 0., 0., 0}}; 

With Slot and MapApply

sum[m_, n_] := Slot[n] & @@@ PadRight[mat //. 0 | 0. | {} :> Nothing] // Total sum[mat, #] & /@ Range[3] 

{121.973, 81.4346, 45.7614}

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.