May 1, 2009

PHP: average functions: Mean (Arithmetic, Geometric, Harmonic) · Median · Mode

See Wiki for detail on mean, median or mode. Please write your own optimizations / implementations in the comments.
function arithmetic_mean($a) {
 return array_sum($a)/count($a);
}

function geometric_mean($a) {
 foreach($a as $i=>$n) $mul = $i == 0 ? $n : $mul*$n;
 return pow($mul,1/count($a));
}

function harmonic_mean($a) {
 $sum = 0;
 foreach($a as $n) $sum += 1 / $n;
 return (1/$sum)*count($a);
}

function median($a) {
 sort($a,SORT_NUMERIC); 
 return (count($a) % 2) ? 
  $a[floor(count($a)/2)] : 
  ($a[floor(count($a)/2)] + $a[floor(count($a)/2) - 1]) / 2;
}

function modal_score($a) {
 $quant = array();
 foreach($a as $n) $quant["$n"]++;
 $max = 0;
 $mode = 0;
 foreach($quant as $key=>$n) {
  if($n>$max) {
   $max = $n;
   $mode = $key;
  }
 }
 return $mode;
}

4 comments:

Anonymous said...

# function median($a) {
# sort($a,SORT_NUMERIC);
# return ($num % 2) ?
# $a[floor(count($a)/2)] :
# ($a[count($a)/2] + $a[count($a)/2 - 1]) / 2;
# }

$num ??

jeancaffou said...

Oooops. Fixed!

Marko Manninen said...

# I was hitting INF with calculating geometric mean, because product of the big list of numbers
# so i had to optimize function for my purpose. I also figured how beautifully geometric and arithmetic means are related. See: http://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_arithmetic_mean_of_logarithms
function geometric_mean($a) {
array_walk($a, function (&$i) {
$i = log($i);
});
return exp(arithmetic_mean($a));
}

function arithmetic_mean($a) {
return array_sum($a) / count($a);
}

Joan said...

Hi! First of all, thanks for share the code! I've used your script in my php code, it's very useful! Moreover, I wanted to say that I've improved your modal_score code. Now, you can have negative numbers to do the modal and if there are more than one number with the same "max", it return all modals scores.

This is the code:

$quant = array();
foreach ($a as $n){
$quant["$n"] ++;
}
$max = null;
$mode = array();
foreach ($quant as $key => $n) {
if ($max == null || $mode == null || $n > $max) {
$max = $n;
$mode = array($key);
} elseif($n == $max){
array_push($mode, $key);
}
}
return $mode;