Implement generic sparklines with tests
This commit is contained in:
parent
51f2fce2c4
commit
53f4e56529
|
@ -0,0 +1,35 @@
|
|||
open Jest
|
||||
open Expect
|
||||
|
||||
let env: DistributionOperation.env = {
|
||||
sampleCount: 100,
|
||||
xyPointLength: 100,
|
||||
}
|
||||
|
||||
let normalDist: GenericDist_Types.genericDist = Symbolic(#Normal({mean: 5.0, stdev: 2.0}))
|
||||
let uniformDist: GenericDist_Types.genericDist = Symbolic(#Uniform({low: 9.0, high: 10.0}))
|
||||
let betaDist: GenericDist_Types.genericDist = Symbolic(#Beta({alpha: 2.0, beta: 5.0}))
|
||||
let lognormalDist: GenericDist_Types.genericDist = Symbolic(#Lognormal({mu: 0.0, sigma: 1.0}))
|
||||
let cauchyDist: GenericDist_Types.genericDist = Symbolic(#Cauchy({local: 1.0, scale: 1.0}))
|
||||
let triangularDist: GenericDist_Types.genericDist = Symbolic(#Triangular({low: 1.0, medium: 2.0, high: 3.0}))
|
||||
let exponentialDist: GenericDist_Types.genericDist = Symbolic(#Exponential({rate: 2.0}))
|
||||
|
||||
let runTest = (name: string, dist : GenericDist_Types.genericDist, expected: string) => {
|
||||
test(name, () => {
|
||||
let result = GenericDist.toSparkline(~xyPointLength=100, ~sampleCount=100, ~buckets=20, dist)
|
||||
switch result {
|
||||
| Ok(sparkline) => expect(sparkline)->toEqual(expected)
|
||||
| Error(err) => expect("Error")->toEqual(expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
describe("sparkline of generic distribution", () => {
|
||||
runTest("normal", normalDist, `▁▁▁▁▂▃▄▆▇██▇▆▄▃▂▁▁▁`)
|
||||
runTest("uniform", uniformDist, `████████████████████`)
|
||||
runTest("beta", uniformDist, `████████████████████`)
|
||||
runTest("lognormal", lognormalDist, `█▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁`)
|
||||
runTest("cauchy", cauchyDist, `▁▁▁▁▁▁▁▁▁██▁▁▁▁▁▁▁▁▁`)
|
||||
runTest("triangular", triangularDist, `▁▂▃▄▄▅▆▇████▇▆▅▄▄▃▂▁`)
|
||||
runTest("exponential", exponentialDist, `█▆▄▃▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁`)
|
||||
})
|
|
@ -49,7 +49,7 @@ let toFloatOperation = (
|
|||
}
|
||||
}
|
||||
|
||||
//Todo: If it's a pointSet, but the xyPointLenght is different from what it has, it should change.
|
||||
//Todo: If it's a pointSet, but the xyPointLength is different from what it has, it should change.
|
||||
// This is tricky because the case of discrete distributions.
|
||||
// Also, change the outputXYPoints/pointSetDistLength details
|
||||
let toPointSet = (~xyPointLength, ~sampleCount, t): result<PointSetTypes.pointSetDist, error> => {
|
||||
|
@ -75,6 +75,9 @@ let toPointSet = (~xyPointLength, ~sampleCount, t): result<PointSetTypes.pointSe
|
|||
}
|
||||
}
|
||||
|
||||
let toSparkline = (~xyPointLength: int, ~sampleCount: int, ~buckets: int = 20, t: t) : result<string, error> =>
|
||||
toPointSet(~xyPointLength, ~sampleCount, t) -> E.R2.fmap(PointSetDist.toSparkline(buckets))
|
||||
|
||||
module Truncate = {
|
||||
let trySymbolicSimplification = (leftCutoff, rightCutoff, t: t): option<t> =>
|
||||
switch (leftCutoff, rightCutoff, t) {
|
||||
|
|
|
@ -24,6 +24,12 @@ let toPointSet: (
|
|||
~sampleCount: int,
|
||||
t,
|
||||
) => result<PointSetTypes.pointSetDist, error>
|
||||
let toSparkline: (
|
||||
~xyPointLength: int,
|
||||
~sampleCount: int,
|
||||
~buckets: int=?,
|
||||
t,
|
||||
) => result<string, error>
|
||||
|
||||
let truncate: (
|
||||
t,
|
||||
|
@ -59,4 +65,4 @@ let mixture: (
|
|||
array<(t, float)>,
|
||||
~scaleMultiplyFn: scaleMultiplyFn,
|
||||
~pointwiseAddFn: pointwiseAddFn,
|
||||
) => result<t, error>
|
||||
) => result<t, error>
|
||||
|
|
|
@ -168,6 +168,22 @@ let pdf = (f: float, t: t) => {
|
|||
let inv = T.Integral.yToX
|
||||
let cdf = T.Integral.xToY
|
||||
|
||||
let diff = (arr: array<float>): array<float> =>
|
||||
Belt.Array.zipBy(arr, Belt.Array.sliceToEnd(arr, 1), (left, right) => right -. left)
|
||||
|
||||
let rec rangeByFloat = (start : float, end: float, step: float) =>
|
||||
start > end ?
|
||||
[]
|
||||
: Belt.Array.concat([start], rangeByFloat(start +. step, end, step))
|
||||
|
||||
@genType
|
||||
let toSparkline = (buckets: int, t: t ): string => {
|
||||
let size : float = T.maxX(t) -. T.minX(t)
|
||||
let stepSize = size /. Belt.Int.toFloat(buckets)
|
||||
let cdf = rangeByFloat(T.minX(t), T.maxX(t), stepSize) -> Belt.Array.map(val => cdf(val,t))
|
||||
Sparklines.create(diff(cdf), ())
|
||||
}
|
||||
|
||||
let doN = (n, fn) => {
|
||||
let items = Belt.Array.make(n, 0.0)
|
||||
for x in 0 to n - 1 {
|
||||
|
|
Loading…
Reference in New Issue
Block a user