Averaging over columns while ignoring zero entries

I have:

list = {{1, 3, 4, 5, 6, 0, 9}, {4, 0, 3, 5, 0, 2, 0},
{1, 0, 2, 2, 2, 4, 0}}


I want to calculate the average but without considering the 0s.

The result should be:

result = Array[0 &, Last@Dimensions@list];

n = Length@result;

Do[
array = list[[All, i]];
total = Total[array];
cnt = Count[array, 0];

If[Length@array - cnt > 0,
result[[i]] = total/(Length@array - cnt),
result[[i]] = 0
];,
{i, 1, n}
];

result // N

{2., 3., 3., 4., 4., 3., 9.}


How can I replace the Do loop?

• Mean /@ DeleteCases[Transpose@list, 0, All] – MarcoB Mar 8 '19 at 14:10
• Thank you for the solution. – lio Mar 8 '19 at 14:12
• You’re welcome. I’ve added an answer since this solution works for you – MarcoB Mar 8 '19 at 14:13
• I'm not at a computer right now, so please try Total[list]/Total[Unitize[list]]. – J. M.'s technical difficulties Mar 8 '19 at 14:21
• @J.M. Well, that is clever! Cool trick :-) – MarcoB Mar 8 '19 at 16:50

I'm posting this as a CW answer, so J.M.'s very nice answer, made in a comment above, gets recorded as a real answer.

list = {{1, 3, 4, 5, 6, 0, 9}, {4, 0, 3, 5, 0, 2, 0}, {1, 0, 2, 2, 2, 4, 0}};
Total[list]/Total[Unitize[list]]


{2, 3, 3, 4, 4, 3, 9}

Update

As J.M. points out in a comment below, there is more robust formulation that handles the cases where one or mort columns contain all zeros.

list = {{1, 3, 4, 5, 6, 0, 0}, {4, 0, 3, 5, 0, 2, 0}, {1, 0, 2, 2, 2, 4, 0}};
Total[list]/(Total[Unitize[list]] /. 0 -> 1)

{2, 3, 3, 4, 4, 3, 0}

• This produces an error for: list = {{1, 3, 4, 5, 6, 0, 0}, {4, 0, 3, 5, 0, 2, 0}, {1, 0, 2, 2, 2, 4, 0}} – lio Mar 11 '19 at 14:58
• @lio, change the denominator to (Total[Unitize[list]] /. 0 -> 1). – J. M.'s technical difficulties Mar 11 '19 at 15:02
Mean /@ DeleteCases[Transpose@list, 0, All]


{2,3,3,4,4,3,9}

• This produces an error for: list = {{1, 3, 4, 5, 6, 0, 0}, {4, 0, 3, 5, 0, 2, 0}, {1, 0, 2, 2, 2, 4, 0}} – lio Mar 11 '19 at 14:58
• @lio, It does not produce an error. It just returns Mean[{}] in the case that all entries are zero. What result would you expect in that case? – MarcoB Mar 11 '19 at 16:09
• I think the OP expects {2, 3, 3, 4, 4, 3, 0} in this case. – m_goldberg Mar 11 '19 at 18:20
ClearAll[means]
means = Mean[#["NonzeroValues"] /. {} -> {0}] & /@ SparseArray[Transpose[#]] &;


Examples:

list1 = {{1, 3, 4, 5, 6, 0, 9}, {4, 0, 3, 5, 0, 2, 0}, {1, 0, 2, 2, 2,  4, 0}};
means @ list1


{2, 3, 3, 4, 4, 3, 9}

list2 = {{1, 3, 4, 5, 6, 0, 0}, {4, 0, 3, 5, 0, 2, 0}, {1, 0, 2, 2, 2,  4, 0}};
means @ list2


{2, 3, 3, 4, 4, 3, 0}