Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assign a rank number to an array when ties exist

Tags:

php

I am struggling to know where to start when trying to assign ranks to the numeric values in an array when there are ties. So, for example, I need to turn an array like the following:

myarray = (4,76,34,13,34)

into another array like:

myarray2 = (1,5,3.5,2,3.5)

Basically, when the same number occurs more than once in the array, the assigned rank to those numbers is the average of the ranks. So, instead of the two 34s being ranked 3 and 4 they both get assigned 3.5. Similarly, if there were 3 copies of 34 then the 3 assigned ranks would be divided by 3. Any help would be much appreciated!

Many thanks,

Adam

like image 481
Adam L. Avatar asked Aug 11 '10 23:08

Adam L.


2 Answers

I had fun with this one!

function rank($input) 
{
  $output = array();
  $ranking = $input; sort($ranking); $ranking = array_flip($ranking);
  $last_val = -1;
  foreach($ranking as $key => $val){
    $repetitions = ($val-$last_val-1);
    $last_val = $val;
    if($repetitions) {    
      $ranking[$key] = (($val*($repetitions+1))-($repetitions+1)*(($repetitions)/2))/($repetitions+1)+1 ;
    } else {
      $ranking[$key] = $val+1;
    }
  }
  foreach($input as $key => $val){
    $output[$key] = $ranking[$val];
  }
  return $output;
}

Use it like this:

$a = array(4,76,34,13,34);    
$c = rank($a);
print_r($c);

will output:

Array
(
    [0] => 1
    [1] => 5
    [2] => 3.5
    [3] => 2
    [4] => 3.5
)

wich is the same as:

Array(1, 5, 3.5, 2, 3.5)

as expected!

like image 79
Sebastián Grignoli Avatar answered Sep 21 '22 17:09

Sebastián Grignoli


Here is one way to do it.

<?php
$myarray       = array(4,76,34,13,34);

$sorted_array  = $myarray;
$grouped_array = array();
sort($sorted_array);
foreach ($sorted_array as $rank => $entry) {
    // Initialize the entry if it doesn't already exist
    if (empty($grouped_array[$entry])) {
        $grouped_array[$entry]['count'] = 1.0;
        $grouped_array[$entry]['total'] = $rank + 1; // Account for 0-based array
    } else {
        $grouped_array[$entry]['count'] += 1.0;
        $grouped_array[$entry]['total'] += $rank + 1; // Account for 0-based array
    }
}
$myarray2 = array();
foreach ($myarray as $entry) {
    // Get the average
    $myarray2[] = $grouped_array[$entry]['total'] / $grouped_array[$entry]['count'];
}
like image 20
pferate Avatar answered Sep 22 '22 17:09

pferate