package scientific.stats.frequencystat
import std.unittest.*
import std.unittest.testmacro.*
import scientific.numbers.*
import scientific.linear.*
public class RelfreqRes {
public let frequency: Vector<Float64>
public let lowerlimit: Float64
public let binsize: Float64
public init (frequency: Vector<Float64>, lowerlimit: Float64, binsize: Float64) {
this.frequency = frequency
this.lowerlimit = lowerlimit
this.binsize = binsize
}
}
public func relfreq(data: Vector<Float64>, limits: (Float64, Float64), weights: Vector<Float64>, numbins!: Int64 = 10): RelfreqRes {
let frequency = vector<Float64>(numbins, 0.0)
let lowerlimit = limits[0]
let binsize = (limits[1] - lowerlimit) / Float64(numbins)
let datasec = vector<Float64>(numbins + 1, 0.0)
for (i in 0..(numbins + 1)) {
datasec[i] = lowerlimit + Float64(i) * binsize
}
let n = data.size()
for (i in 0..n) {
for (j in 0..numbins) {
if (data[i] >= datasec[j] && data[i] < datasec[j + 1]) {
frequency[j] += weights[i]
break
} else if (j == (numbins - 1) && data[i] == datasec[j + 1]) {
frequency[j] += weights[i]
break
}
}
}
for (i in 0..numbins) {
frequency[i] = frequency[i] / Float64(n)
}
return RelfreqRes(frequency, lowerlimit, binsize)
}
public func relfreq(data: Vector<Float64>, numbins!: Int64 = 10): RelfreqRes {
let l = min(data)
let r = max(data)
let s = 0.5 * (r - l) / Float64(numbins - 1)
let limits = (l - s, r + s)
let n = data.size()
let weights = vector<Float64>(n, 1.0)
return relfreq(data, limits, weights, numbins: numbins)
}
public func relfreq(data: Vector<Float64>, limits: (Float64, Float64), numbins!: Int64 = 10): RelfreqRes {
let n = data.size()
let weights = vector<Float64>(n, 1.0)
return relfreq(data, limits, weights, numbins: numbins)
}
public func relfreq(data: Vector<Float64>, weights: Vector<Float64>, numbins!: Int64 = 10): RelfreqRes {
let l = min(data)
let r = max(data)
let s = 0.5 * (r - l) / Float64(numbins - 1)
let limits = (l - s, r + s)
return relfreq(data, limits, weights, numbins: numbins)
}
@Test
public class TestRelFreq {
@TestCase
func testRelfreq(): Unit {
let data = vector<Float64>([1.0, 3.0, 27.0, 2.0, 5.0, 13.0])
let res = relfreq(data, numbins: 4)
@Assert(approxEqual(res.frequency, vector([0.66666667, 0.16666667, 0.0, 0.16666667])))
@Assert(approxEqual(res.lowerlimit, -3.33333333333, atol:1e-6))
@Assert(approxEqual(res.binsize, 8.66666666667, atol:1e-6) )
}
}