Simple visualization of probability distribution
This commit is contained in:
parent
5046a04c40
commit
b8d0368313
|
@ -15,6 +15,7 @@
|
||||||
"suffix": ".bs.js",
|
"suffix": ".bs.js",
|
||||||
"namespace": true,
|
"namespace": true,
|
||||||
"bs-dependencies": [
|
"bs-dependencies": [
|
||||||
|
"@foretold/components",
|
||||||
"bs-ant-design-alt",
|
"bs-ant-design-alt",
|
||||||
"reason-react",
|
"reason-react",
|
||||||
"bs-reform",
|
"bs-reform",
|
||||||
|
@ -25,5 +26,5 @@
|
||||||
"refmt": 3,
|
"refmt": 3,
|
||||||
"ppx-flags": [
|
"ppx-flags": [
|
||||||
"lenses-ppx/ppx"
|
"lenses-ppx/ppx"
|
||||||
],
|
]
|
||||||
}
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@foretold/cdf": "^1.0.14",
|
"@foretold/cdf": "^1.0.14",
|
||||||
|
"@foretold/components": "^0.0.3",
|
||||||
"@foretold/guesstimator": "^1.0.10",
|
"@foretold/guesstimator": "^1.0.10",
|
||||||
"antd": "3.17.0",
|
"antd": "3.17.0",
|
||||||
"autoprefixer": "^9.7.4",
|
"autoprefixer": "^9.7.4",
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
"bs-reform": "9.7.1",
|
"bs-reform": "9.7.1",
|
||||||
"lenses-ppx": "4.0.0",
|
"lenses-ppx": "4.0.0",
|
||||||
"less": "^3.10.3",
|
"less": "^3.10.3",
|
||||||
|
"lodash": "^4.17.15",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"parcel-bundler": "^1.12.4",
|
"parcel-bundler": "^1.12.4",
|
||||||
"parcel-plugin-less-js-enabled": "^1.0.2",
|
"parcel-plugin-less-js-enabled": "^1.0.2",
|
||||||
|
@ -42,10 +44,14 @@
|
||||||
"reschema": "^1.3.0"
|
"reschema": "^1.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"bs-platform": "^5.0.6",
|
"bs-platform": "5.2.1",
|
||||||
"bsb-js": "^1.1.7",
|
"bsb-js": "^1.1.7",
|
||||||
"gh-pages": "^2.2.0",
|
"gh-pages": "^2.2.0",
|
||||||
"moduleserve": "^0.9.0",
|
"moduleserve": "^0.9.0",
|
||||||
"tailwindcss": "^1.2.0"
|
"tailwindcss": "^1.2.0"
|
||||||
|
},
|
||||||
|
"alias": {
|
||||||
|
"react": "./node_modules/react",
|
||||||
|
"react-dom": "./node_modules/react-dom"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,10 +51,7 @@ module ModelForm = {
|
||||||
)
|
)
|
||||||
|> ReasonReact.array}
|
|> ReasonReact.array}
|
||||||
<div className="bg-green-100 p-2 rounded-sm mt-6 text-lg">
|
<div className="bg-green-100 p-2 rounded-sm mt-6 text-lg">
|
||||||
{model.run(formState.combo)
|
{model.run(formState.combo) |> E.O.React.fmapOrNull(Value.display)}
|
||||||
|> E.O.fmap(Value.to_string)
|
|
||||||
|> E.O.default("")
|
|
||||||
|> ReasonReact.string}
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>;
|
</div>;
|
||||||
|
|
|
@ -18,12 +18,43 @@ module Value = {
|
||||||
| Unselected => ""
|
| Unselected => ""
|
||||||
}
|
}
|
||||||
| SelectSingle(r) => r
|
| SelectSingle(r) => r
|
||||||
| FloatCdf(r) => r
|
| FloatCdf(r) =>
|
||||||
|
let foo: Types.distribution =
|
||||||
|
CdfLibrary.Distribution.fromString(r, 100);
|
||||||
|
r;
|
||||||
| Probability(r) => (r *. 100. |> Js.Float.toFixed) ++ "%"
|
| Probability(r) => (r *. 100. |> Js.Float.toFixed) ++ "%"
|
||||||
| DateTime(r) => r |> MomentRe.Moment.defaultFormat
|
| DateTime(r) => r |> MomentRe.Moment.defaultFormat
|
||||||
| FloatPoint(r) => r |> Js.Float.toFixed
|
| FloatPoint(r) => r |> Js.Float.toFixed
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let display = (t: t) => {
|
||||||
|
switch (t) {
|
||||||
|
| BinaryConditional(binaryConditional) =>
|
||||||
|
(
|
||||||
|
switch (binaryConditional) {
|
||||||
|
| Selected(r) => r ? "True" : "False"
|
||||||
|
| Unselected => ""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|> ReasonReact.string
|
||||||
|
| SelectSingle(r) => r |> ReasonReact.string
|
||||||
|
| FloatCdf(r) =>
|
||||||
|
let cdf: Types.distribution =
|
||||||
|
CdfLibrary.Distribution.fromString(r, 100);
|
||||||
|
<>
|
||||||
|
<ForetoldComponents.CdfChart__Large
|
||||||
|
cdf={Types.toComponentsDist(cdf)}
|
||||||
|
width={Some(400)}
|
||||||
|
/>
|
||||||
|
{r |> ReasonReact.string}
|
||||||
|
</>;
|
||||||
|
| Probability(r) =>
|
||||||
|
(r *. 100. |> Js.Float.toFixed) ++ "%" |> ReasonReact.string
|
||||||
|
| DateTime(r) => r |> MomentRe.Moment.defaultFormat |> ReasonReact.string
|
||||||
|
| FloatPoint(r) => r |> Js.Float.toFixed |> ReasonReact.string
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
module Type = {
|
module Type = {
|
||||||
|
|
|
@ -2,3 +2,8 @@ type distribution = {
|
||||||
xs: array(float),
|
xs: array(float),
|
||||||
ys: array(float),
|
ys: array(float),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let toComponentsDist = (d: distribution): ForetoldComponents.Types.Dist.t => {
|
||||||
|
xs: d.xs,
|
||||||
|
ys: d.ys,
|
||||||
|
};
|
|
@ -14,26 +14,26 @@ module JS = {
|
||||||
|
|
||||||
let doAsDist = (f, d: Types.distribution) => d |> distToJs |> f |> jsToDist;
|
let doAsDist = (f, d: Types.distribution) => d |> distToJs |> f |> jsToDist;
|
||||||
|
|
||||||
[@bs.module "./CdfLibraryImporter.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external cdfToPdf: distJs => distJs = "cdfToPdf";
|
external cdfToPdf: distJs => distJs = "cdfToPdf";
|
||||||
|
|
||||||
[@bs.module "./CdfLibraryImporter.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external pdfToCdf: distJs => distJs = "pdfToCdf";
|
external pdfToCdf: distJs => distJs = "pdfToCdf";
|
||||||
|
|
||||||
[@bs.module "./CdfLibraryImporter.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external findY: (float, distJs) => float = "findY";
|
external findY: (float, distJs) => float = "findY";
|
||||||
|
|
||||||
[@bs.module "./CdfLibraryImporter.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external findX: (float, distJs) => float = "findX";
|
external findX: (float, distJs) => float = "findX";
|
||||||
|
|
||||||
[@bs.module "./CdfLibraryImporter.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external integral: distJs => float = "integral";
|
external integral: distJs => float = "integral";
|
||||||
|
|
||||||
[@bs.module "./CdfLibraryImporter.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external differentialEntropy: (int, distJs) => distJs =
|
external differentialEntropy: (int, distJs) => distJs =
|
||||||
"differentialEntropy";
|
"differentialEntropy";
|
||||||
|
|
||||||
[@bs.module "./CdfLibraryImporter.js"]
|
[@bs.module "./CdfLibrary.js"]
|
||||||
external scoreNonMarketCdfCdf: (int, distJs, distJs, float) => distJs =
|
external scoreNonMarketCdfCdf: (int, distJs, distJs, float) => distJs =
|
||||||
"scoreNonMarketCdfCdf";
|
"scoreNonMarketCdfCdf";
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,51 @@
|
||||||
import { Guesstimator } from '@foretold/guesstimator';
|
import { Guesstimator } from '@foretold/guesstimator';
|
||||||
import { Samples } from '@foretold/cdf';
|
import { Samples } from '@foretold/cdf';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
const toPdf = (values, min, max) => {
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} minValue
|
||||||
|
* @param {number} maxValue
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
const minMaxRatio = (minValue, maxValue) => {
|
||||||
|
if (minValue === 0 || maxValue === 0) {
|
||||||
|
return 'SMALL';
|
||||||
|
}
|
||||||
|
const ratio = maxValue / minValue;
|
||||||
|
if (ratio < 100000) {
|
||||||
|
return 'SMALL';
|
||||||
|
} else if (ratio < 10000000) {
|
||||||
|
return 'MEDIUM';
|
||||||
|
} else {
|
||||||
|
return 'LARGE';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param samples
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
const ratioSize = samples => {
|
||||||
|
samples.sort();
|
||||||
|
const minValue = samples.getPercentile(2);
|
||||||
|
const maxValue = samples.getPercentile(98);
|
||||||
|
return minMaxRatio(minValue, maxValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const toPdf = (values, sampleCount, min, max) => {
|
||||||
const samples = new Samples(values);
|
const samples = new Samples(values);
|
||||||
|
|
||||||
const ratioSize$ = ratioSize(samples);
|
const ratioSize$ = ratioSize(samples);
|
||||||
const width = ratioSize$ === 'SMALL' ? 20 : 1;
|
const width = ratioSize$ === 'SMALL' ? 20 : 1;
|
||||||
|
|
||||||
const pdf = samples.toPdf({ size: 1000, width, min, max });
|
const cdf = samples.toCdf({ size: sampleCount, width, min, max });
|
||||||
return {ys:pdf.ys, xs:pdf.xs};
|
return {ys:cdf.ys, xs:cdf.xs};
|
||||||
};
|
};
|
||||||
|
|
||||||
let run = (text, sampleCount, inputs=[], min=false, max=false) => {
|
let run = (text, sampleCount, inputs=[], min=false, max=false) => {
|
||||||
let [_error, item] = Guesstimator.parse({ text });
|
console.log(text);
|
||||||
|
let [_error, item] = Guesstimator.parse({ text: "=" + text });
|
||||||
const { parsedInput } = item;
|
const { parsedInput } = item;
|
||||||
const { guesstimateType } = parsedInput;
|
const { guesstimateType } = parsedInput;
|
||||||
|
|
||||||
|
@ -25,18 +58,13 @@ let run = (text, sampleCount, inputs=[], min=false, max=false) => {
|
||||||
|
|
||||||
const values = _.filter(value.values, _.isFinite);
|
const values = _.filter(value.values, _.isFinite);
|
||||||
|
|
||||||
this.setState({
|
|
||||||
value: event.target.value,
|
|
||||||
items: values,
|
|
||||||
});
|
|
||||||
|
|
||||||
let update;
|
let update;
|
||||||
if (values.length === 0) {
|
if (values.length === 0) {
|
||||||
update = {xs: [], ys: []};
|
update = {xs: [], ys: []};
|
||||||
} else if (values.length === 1) {
|
} else if (values.length === 1) {
|
||||||
update = {xs: [], ys: []};
|
update = {xs: [], ys: []};
|
||||||
} else {
|
} else {
|
||||||
update = toPdf(values, min, max);
|
update = toPdf(values, sampleCount, min, max);
|
||||||
}
|
}
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user