I have two arrays, percentiles
and percentile_bounds
and another int value total_score
. Given the total score, I want to return the percentile in which this value is. Ie. I want to return a value from percentiles
which corresponds to placing the total_score
within the percentile_bounds
. In python, I would do:
import numpy as np
percentiles = np.array([ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95])
percentile_bounds = np.array([ 84, 104, 109, 115, 120, 123, 125, 127, 129, 132, 135, 136, 137, 139, 141, 145, 148, 151, 155, 159])
# example 1
total_score = 130
print(percentiles[np.where(percentile_bounds==(percentile_bounds[percentile_bounds<total_score][-1]))])
# 40
# example 2
total_score = 153
print(percentiles[np.where(percentile_bounds==(percentile_bounds[percentile_bounds<total_score][-1]))])
# 85
# example 3
total_score = 100
print(percentiles[np.where(percentile_bounds==(percentile_bounds[percentile_bounds<total_score][-1]))])
# 0
and I found a way in PHP (function sources: 1, 2) but it is very clumsy and long:
<?php
// Example 4
$total_score = 120;
$percentile_bounds = [84, 104, 109, 115, 120, 123, 125, 127, 129, 132, 135, 136, 137,139, 141, 145, 148, 151, 155, 159];
$percentiles = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95];
// get the last element from percentile_bounds which is less than total_score
$value = end(array_filter($percentile_bounds, function ($x) use ($total_score) { return $x < $total_score; }));
// find its index
$key = array_search($value, $percentile_bounds);
// find the corresponding value in percentiles
echo "percentile: $percentiles[$key]";
// 15
Is there a better way of selecting the element from one array (percentiles
) based on a position of an element (total_score
) in the other array (percentile_bounds
)?
Thanks
Note: it is not a duplicate of this.
Clarification: For total_score<=84
the result should be 0 (based on how percentiles work) but it also should not happen. In the code above I do not deal with this condition so it's ok not to but if the solution does, the better :). Thanks @jspit for pointing it out!
CodePudding user response:
foreach
would be more readable and performant approach compared to array_filter
$total_score = 153;
$percentile_bounds = [84, 104, 109, 115, 120, 123, 125, 127, 129, 132, 135, 136, 137, 139, 141, 145, 148, 151, 155, 159];
$percentiles = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95];
foreach ($percentile_bounds as $key => $bound) {
if ($bound > $total_score) {
echo 'percentile: ' . $percentiles[max(0, $key - 1)];
break;
}
}
CodePudding user response:
echo $percentiles[max(array_keys(array_filter($percentile_bounds,function ($x) use ($total_score){return $x<$total_score; })))]