Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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$$

share

3 Answers 3

up vote 5 down vote accepted
 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} *)
share
    
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. –  sebastian c. Nov 16 '12 at 2:27
    
@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.) –  kguler Nov 16 '12 at 2:37
    
thanks for your clarification. –  sebastian c. Nov 16 '12 at 2:47

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}

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

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.

share

This site is currently not accepting new answers.

Not the answer you're looking for? Browse other questions tagged .