emphasized textGiven an array of numbers, I am looking to find the percentile of a given value.
I found this code here that seems to do what I need, but I was hoping I could get someone to explain this code to me step by step:
const percentile = (arr, val) =>
(100 *
arr.reduce(
(acc, v) => acc (v < val ? 1 : 0) (v === val ? 0.5 : 0),
0
)) /
arr.length;
// example
// percentile([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6); // 55
Update
Thanks everyone for your help. I found a Percentile formula that further helps me understand what the code is doing.
Formula:
Percentile = [L ( 0.5 x S ) / N] * 100
- L = Number of below rank
- S = Number of same rank
- N = Total numbers
Based on my new understanding of the function, I find this a bit easier to read:
/**
* **Percentile = ((L ( 0.5 x S )) / N) * 100**
* - L = Number of values **lower** than `value`
* - S = Number of same rank
* - N = Total numbers
*/
const percentile = (arr, value) => {
const currentIndex = 0;
const totalCount = arr.reduce((count, currentValue) => {
if (currentValue < value) {
return count 1; // add 1 to `count`
} else if (currentValue === value) {
return count 0.5; // add 0.5 to `count`
}
return count 0;
}, currentIndex);
return (totalCount * 100) / arr.length;
};
CodePudding user response:
The function is equivalent to ths simpler version.
count
contains the number of elements that val
is higher than, plus 0.5 for each element it's equal to. Dividing this total by the number of elements is the percentile.
const percentile = (arr, val) => {
let count = 0;
arr.forEach(v => {
if (v < val) {
count ;
} else if (v == val) {
count = 0.5;
}
});
return 100 * count / arr.length;
}
console.log(percentile([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 6));
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Even if the vector is not sorted the result is correct. The vector can contain duplicated values.
reduce scan a vector and produce a result accumulating partial results inside the acc
acc is initialized to 0 (line 5)
(v < val ? 1 : 0) result in 1 or 0 depending if v < val. The conditional ternary operator ? : is not needed because true is interpreted as 1 and false as 0, so you can write only (v < val)
(v === val ? 0.5 : 0) add .5 only for values equal to the val.
Lines 2 and 7 transform the frequency of lower (and equal) values into a percentile.
CodePudding user response:
Step-by-step explanation
- A constant named "percentile" is defined and passes two arguments, an array "arr" and a value "val", to the given function...
- The reduce() method is called on the array. This takes a function as an argument (called a reducer function), as well as an optional argument initialValue, which is defined here as 0 (zero).
- The reducer function creates an empty number variable "acc". The variable "v" refers to the current value, as taken from the array "arr".
- The reduce method iterates through each value in
arr
(aka it sets each element inarr
asv
). On each iteration... - The reducer function compares
v
toval
. Ifv
is less thanval
, thenacc
is increased by 1. Ifv
is equal toval
, thenacc
is increased by 0.5. (In layperson's terms, this means that as the function iterates through each element inarr
, the value ofacc
is counting how many elements are less than or equal toval
.) - After the function has iterated through every element of the array,
acc
is divided by the number of elements inarr
. (In other words, sinceacc
is the number of elements that are less thanval
, dividingacc
/arr
gives us a decimal representing the proportion of the array that's less thanval
.) - That number is multiplied by 100 to turn the decimal into a percentage.