Basic mixed discrete-continuous distributions

This commit is contained in:
Ozzie Gooen 2020-02-15 23:27:25 +00:00
parent beda0b61ed
commit 03cc7293a4
4 changed files with 35 additions and 14 deletions

View File

@ -61,13 +61,10 @@ module Value = {
let newDistribution = let newDistribution =
GenericDistribution.renderIfNeeded(~sampleCount=1000, r); GenericDistribution.renderIfNeeded(~sampleCount=1000, r);
switch (newDistribution) { switch (newDistribution) {
| Some({generationSource: Shape(Mixed({continuous: n}))}) => | Some({generationSource: Shape(Mixed({continuous: n, discrete: d}))}) =>
<div> <div>
<Chart height=100 data={n |> Shape.Continuous.toJs} /> <Chart height=100 data={n |> Shape.Continuous.toJs} />
<Chart {Shape.Discrete.render(d)}
height=100
data={n |> Shape.Continuous.toCdf |> Shape.Continuous.toJs}
/>
</div> </div>
| None => "Something went wrong" |> ReasonReact.string | None => "Something went wrong" |> ReasonReact.string
| _ => <div /> | _ => <div />

View File

@ -45,6 +45,18 @@ module Discrete = {
|> Belt.Array.unzip; |> Belt.Array.unzip;
fromArrays(xs, ys); fromArrays(xs, ys);
}; };
let render = (t: t) =>
Belt.Array.zip(t.xs, t.ys)
|> E.A.fmap(((x, y)) =>
<div>
{E.Float.toFixed(x)
++ "---"
++ E.Float.with3DigitsPrecision(y *. 100.)
|> ReasonReact.string}
</div>
)
|> ReasonReact.array;
}; };
module Mixed = { module Mixed = {

View File

@ -1,8 +1,10 @@
// ~generationSource=GuesstimatorString(FloatCdf.logNormal(20., 3.)),
module Model = { module Model = {
let make = (currentDateTime: MomentRe.Moment.t) => { let make = (currentDateTime: MomentRe.Moment.t) => {
let genericDistribution = let genericDistribution =
GenericDistribution.make( GenericDistribution.make(
~generationSource=GuesstimatorString(FloatCdf.logNormal(20., 3.)), ~generationSource=
GuesstimatorString("mm(floor(10 to 15), 20 to 30, [.5,.5])"),
~probabilityType=Cdf, ~probabilityType=Cdf,
~domain=RightLimited({xPoint: 200., excludingProbabilityMass: 0.3}), ~domain=RightLimited({xPoint: 200., excludingProbabilityMass: 0.3}),
~unit=Time({zero: currentDateTime, unit: `years}), ~unit=Time({zero: currentDateTime, unit: `years}),

View File

@ -37,15 +37,21 @@ const ratioSize = samples => {
const toPdf = (values, sampleCount, min, max) => { const toPdf = (values, sampleCount, min, max) => {
let duplicateSamples = _(values).groupBy().pickBy(x => x.length > 1).keys().value(); let duplicateSamples = _(values).groupBy().pickBy(x => x.length > 1).keys().value();
let totalLength = _.size(values); let totalLength = _.size(values);
let frequencies = duplicateSamples.map(s => ({value: parseFloat(s), percentage: totalLength/_(values).filter(x => x ==s).size()})); let frequencies = duplicateSamples.map(s => ({value: parseFloat(s), percentage: _(values).filter(x => x ==s).size()/totalLength}));
let continuousSamples = _.difference(values, frequencies.map(f => f.value)); let continuousSamples = _.difference(values, frequencies.map(f => f.value));
let discrete = {xs: frequencies.map(f => f.value), ys: frequencies.map(f => f.percentage)};
let continuous = {ys: [], xs: []};
if (continuousSamples.length > 1){
const samples = new Samples(continuousSamples); const samples = new Samples(continuousSamples);
const ratioSize$ = ratioSize(samples); const ratioSize$ = ratioSize(samples);
const width = ratioSize$ === 'SMALL' ? 20 : 1; const width = ratioSize$ === 'SMALL' ? 20 : 1;
const cdf = samples.toCdf({ size: sampleCount, width, min, max }); const cdf = samples.toCdf({ size: sampleCount, width, min, max });
return {continuous:{ys:cdf.ys, xs:cdf.xs}, discrete: {xs: frequencies.map(f => f.value), ys: frequencies.map(f => f.percentage)}}; continuous = cdf;
}
return {continuous, discrete};
}; };
let run = (text, sampleCount, inputs=[], min=false, max=false) => { let run = (text, sampleCount, inputs=[], min=false, max=false) => {
@ -63,10 +69,14 @@ let run = (text, sampleCount, inputs=[], min=false, max=false) => {
const values = _.filter(value.values, _.isFinite); const values = _.filter(value.values, _.isFinite);
let update; let update;
let blankResponse = {
continuous: {ys: [], xs: []},
discrete: {ys: [], xs: []}
};
if (values.length === 0) { if (values.length === 0) {
update = {xs: [], ys: []}; update = blankResponse;
} else if (values.length === 1) { } else if (values.length === 1) {
update = {xs: [], ys: []}; update = blankResponse;
} else { } else {
update = toPdf(values, sampleCount, min, max); update = toPdf(values, sampleCount, min, max);
} }