package scientific.stats.frequencystat
import std.unittest.*
import std.unittest.testmacro.*
import scientific.numbers.*
import scientific.linear.*
public class CumfreqRes {
public let cumcount: Vector<Float64>
public let lowerlimit: Float64
public let binsize: Float64
public init(cumcount: Vector<Float64>, lowerlimit: Float64, binsize: Float64) {
this.cumcount = cumcount
this.lowerlimit = lowerlimit
this.binsize = binsize
}
}
public func cumfreq(data: Vector<Float64>, limits: (Float64, Float64), weights: Vector<Float64>, numbins!: Int64 = 10): CumfreqRes {
let cumcount = 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]) {
cumcount[j] += weights[i]
break
} else if(j == (numbins - 1) && data[i] == datasec[j + 1]) {
cumcount[j] += weights[i]
break
}
}
}
for(i in 1..numbins) {
cumcount[i] = cumcount[i - 1] + cumcount[i]
}
return CumfreqRes(cumcount, lowerlimit, binsize)
}
public func cumfreq(data: Vector<Float64>, numbins!: Int64 = 10): CumfreqRes {
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 cumfreq(data, limits, weights, numbins: numbins)
}
public func cumfreq(data: Vector<Float64>, limits: (Float64, Float64), numbins!: Int64 = 10): CumfreqRes {
let n = data.size()
let weights = vector<Float64>(n, 1.0)
return cumfreq(data, limits, weights, numbins: numbins)
}
public func cumfreq(data: Vector<Float64>, weights: Vector<Float64>, numbins!: Int64 = 10): CumfreqRes {
let l = min(data)
let r = max(data)
let s = 0.5 * (r - l) / Float64(numbins - 1)
let limits = (l - s, r + s)
return cumfreq(data, limits, weights, numbins: numbins)
}
@Test
public class TestCumFreq {
@TestCase
func testCumfreq(): Unit {
let data = vector([1.0, 3.0, 27.0, 2.0, 5.0, 13.0])
let res = cumfreq(data, numbins: 4)
@Assert(approxEqual(res.cumcount, vector([4.0, 5.0, 5.0, 6.0])))
@Assert(approxEqual(res.lowerlimit, -3.33333333333, atol:1e-6))
@Assert(approxEqual(res.binsize, 8.66666666667, atol:1e-6))
}
}