Reputation: 71
I need to replicate the Matlab Percentile ( https://www.mathworks.com/help/stats/prctile.html ) for a simple case
percentile(double[] arr, int percentile)
in java. I am unable to find any implementations which give me the same result since it seems to have a percentile along with linear interpolation.
Any help or guidance is appreciated!
Upvotes: 0
Views: 179
Reputation: 1
The @josejuan's answer is very good: but is it not necessary to handle the case in which i
is equal to xs.length - 1
? I would modify the return
formula of percentile
function as follows:
return i != (xs.length - 1) ? xs[i] + (xs[i + 1] - xs[i]) * (p / 100.0 - (i + 0.5) / xs.length) / ((i + 1.5) / xs.length - (i + 0.5) / xs.length) : xs[i];
Upvotes: 0
Reputation: 9566
By directly applying the definition (you can found in the page you've linked)
// `xs` must be sorted
double percentile(double [] xs, int p) {
// The sorted elements in X are taken as the 100(0.5/n)th, 100(1.5/n)th, ..., 100([n – 0.5]/n)th percentiles.
int i = (int) (p * xs.length / 100.0 - 0.5);
// Linear interpolation uses linear polynomials to find yi = f(xi), the values of the underlying function
// Y = f(X) at the points in the vector or array x. Given the data points (x1, y1) and (x2, y2), where
// y1 = f(x1) and y2 = f(x2), linear interpolation finds y = f(x) for a given x between x1 and x2 as follows:
return xs[i] + (xs[i + 1] - xs[i]) * (p / 100.0 - (i + 0.5) / xs.length) / ((i + 1.5) / xs.length - (i + 0.5) / xs.length);
}
using the example on that page
double [] xs1 = new double[] {6.0753, 8.6678, 0.4823, 6.7243, 5.6375, 2.3846, 4.1328, 5.6852, 12.1568, 10.5389};
Arrays.sort(xs1);
double r = percentile(xs1, 42);
System.out.println("Result: " + r);
System.out.println("Error: " + Math.abs(r - 5.6709));
you get
Result: 5.67089
Error: 9.999999999621423E-6
Upvotes: 1