package scientific.stats.frequencystat
import std.math.*
import std.unittest.*
import std.unittest.testmacro.*
import scientific.numbers.*
import scientific.linear.*
public func percentileofscore(data: Vector<Float64>, score: Float64, kind!: String = "rank"): Float64 {
var res = 0.0
let n = data.size()
var m1 = 0
var m2 = 0
var m = 0.0
if (n == 0) {
return Float64.NaN
}
for (i in 0..n) {
if (data[i] <= score) {
m1 += 1
}
if (data[i] < score) {
m2 += 1
}
}
if (kind == "rank") {
m = Float64(m2 + 1 + m1) * 0.5
} else if (kind == "weak") {
m = Float64(m1)
} else if (kind == "strict") {
m = Float64(m2)
} else if (kind == "mean") {
m = Float64(m2 + m1) * 0.5
}
res = m / Float64(n) * 100.0
return res
}
public func percentileofscore(data: Vector<Float64>, score: Vector<Float64>, kind!: String = "rank"): Vector<Float64> {
let len = score.size()
var res = vector<Float64>(len, 0.0)
if (data.size() == 0) {
return vector<Float64>(len, Float64.NaN)
}
for (i in 0..len) {
res[i] = percentileofscore(data, score[i], kind: kind)
}
return res
}
@Test
public class TestPercentileScore {
@TestCase
func testPercentileofscore(): Unit {
let data = vector<Float64>([1.0, 2.0, 3.0, 3.0, 4.0])
let res1 = percentileofscore(data, 3.0)
@Assert(approxEqual(res1, 70.0, atol:0.1))
let res2 = percentileofscore(data, 3.0, kind: "strict")
@Assert(approxEqual(res2, 40.0, atol:0.1))
let res3 = percentileofscore(data, 3.0, kind: "weak")
@Assert(approxEqual(res3, 80.0, atol:0.1))
let res4 = percentileofscore(data, 3.0, kind: "mean")
@Assert(approxEqual(res4, 60.0, atol:0.1))
}
}