Getting the average of only nonzero elements of a matrix

991 views
Skip to first unread message

Jude

unread,
Jul 28, 2015, 11:50:53 AM7/28/15
to julia-users
Hi!

Probably a quite basic question but was wondering if someone knows a quick way to get the average of theh positive elements of a matrix, eg, If I have an m*n matrix and want to get the average for each m so have m*1 but only want to work with non-zero elements and ignore the zero elements and negative elements

I guess I could using indexing and pull out the indexes corresponding to the positive elements but just wondering if anyone knew quicker ways!

Thanks!

Stefan Karpinski

unread,
Jul 28, 2015, 12:01:44 PM7/28/15
to Julia Users
You mean quicker as in faster or as in easier? Using indexing is probably easiest but not fastest:

julia> M = randn(5,5)
5x5 Array{Float64,2}:
 -1.51134     1.2331    -0.186083   0.412282  -1.13114
 -0.0411132   0.124684   0.377426   0.622427  -0.278162
  0.788182   -0.834092   1.09506    1.45196   -0.620717
  1.45856    -0.889277  -0.768049  -0.95953   -0.340098
  1.69666     0.695566   0.706905   0.63089    0.958474

julia> mean(M[M .> 0])
0.8751552351448673

If you want the fastest, loop through the matrix and keep totals and counts:

julia> function meanpos(a)
           t = zero(eltype(a))
           c = 0
           for x in a
               x > 0 || continue
               t += x
               c += 1
           end
           return t/c
       end
meanpos (generic function with 1 method)

julia> meanpos(M)
0.8751552351448673

This should be fairly efficient for any non-sparse collection.

Tom Breloff

unread,
Jul 28, 2015, 12:03:38 PM7/28/15
to julia-users
I would just write the loop explicitly:


julia> function meanpositives(mat::Matrix)
           nc = size(mat,2)
           sums = zeros(nc)
           counts = zeros(nc)
           for c in 1:nc
               for r in 1:size(mat,1)
                   v = mat[r,c]
                   if v > 0
                       sums[c] += v
                       counts[c] += 1.0
                   end
               end
           end
           Float64[(counts[i]>0 ? sums[i]/counts[i] : 0.0) for i in 1:nc]
       end
meanpositives (generic function with 1 method)

julia> x
3x3 Array{Float64,2}:
 10.0  5.0  0.0
  5.0  0.0  0.0
  0.0  0.0  0.0

julia> meanpositives(x)
3-element Array{Float64,1}:
 7.5
 5.0
 0.0

Stefan Karpinski

unread,
Jul 28, 2015, 12:06:00 PM7/28/15
to Julia Users
Oh, didn't catch that you wanted row sums, but yeah, same basic idea.

Tom Breloff

unread,
Jul 28, 2015, 12:10:50 PM7/28/15
to julia-users
Heh... neither did I... I gave you code for column sums!  Should be easy enough to convert...

Jude

unread,
Jul 28, 2015, 12:12:06 PM7/28/15
to julia-users, ste...@karpinski.org
Thanks Stefan and Tom, that's really helpful!  Stefan, I meant quicker as in faster.

Thanks a lot!
Reply all
Reply to author
Forward
0 new messages