Add simple percentiles to distribution shower
This commit is contained in:
parent
c9161d230e
commit
f887af22ea
|
@ -6,6 +6,9 @@ let showAsForm = (distPlus: DistTypes.distPlus) => {
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let showFloat = (~precision=3, number) =>
|
||||||
|
<ForetoldComponents.NumberShower number precision />;
|
||||||
|
|
||||||
let table = (distPlus, x) => {
|
let table = (distPlus, x) => {
|
||||||
<div>
|
<div>
|
||||||
<table className="table-auto text-sm">
|
<table className="table-auto text-sm">
|
||||||
|
@ -120,6 +123,60 @@ let table = (distPlus, x) => {
|
||||||
</table>
|
</table>
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
let percentiles = distPlus => {
|
||||||
|
<table className="table-auto text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2"> {"1" |> ReasonReact.string} </td>
|
||||||
|
<td className="px-4 py-2"> {"5" |> ReasonReact.string} </td>
|
||||||
|
<td className="px-4 py-2"> {"25" |> ReasonReact.string} </td>
|
||||||
|
<td className="px-4 py-2"> {"50" |> ReasonReact.string} </td>
|
||||||
|
<td className="px-4 py-2"> {"75" |> ReasonReact.string} </td>
|
||||||
|
<td className="px-4 py-2"> {"95" |> ReasonReact.string} </td>
|
||||||
|
<td className="px-4 py-2"> {"99" |> ReasonReact.string} </td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.01)
|
||||||
|
|> showFloat}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 border">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.05)
|
||||||
|
|> showFloat}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 border">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.25)
|
||||||
|
|> showFloat}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 border">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.5)
|
||||||
|
|> showFloat}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 border">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.75)
|
||||||
|
|> showFloat}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 border">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.95)
|
||||||
|
|> showFloat}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 border">
|
||||||
|
{distPlus
|
||||||
|
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.99)
|
||||||
|
|> showFloat}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>;
|
||||||
|
};
|
||||||
|
|
||||||
let adjustBoth = discreteProbabilityMass => {
|
let adjustBoth = discreteProbabilityMass => {
|
||||||
let yMaxDiscreteDomainFactor = discreteProbabilityMass;
|
let yMaxDiscreteDomainFactor = discreteProbabilityMass;
|
||||||
|
@ -287,8 +344,12 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
||||||
|> E.L.toArray
|
|> E.L.toArray
|
||||||
|> ReasonReact.array}
|
|> ReasonReact.array}
|
||||||
<div className="inline-flex opacity-50 hover:opacity-100">
|
<div className="inline-flex opacity-50 hover:opacity-100">
|
||||||
|
<button
|
||||||
|
className=button onClick={_ => dispatch(CHANGE_SHOW_PERCENTILES)}>
|
||||||
|
{"Percentiles" |> ReasonReact.string}
|
||||||
|
</button>
|
||||||
<button className=button onClick={_ => dispatch(CHANGE_SHOW_STATS)}>
|
<button className=button onClick={_ => dispatch(CHANGE_SHOW_STATS)}>
|
||||||
{"Stats" |> ReasonReact.string}
|
{"Debug Stats" |> ReasonReact.string}
|
||||||
</button>
|
</button>
|
||||||
<button className=button onClick={_ => dispatch(CHANGE_SHOW_PARAMS)}>
|
<button className=button onClick={_ => dispatch(CHANGE_SHOW_PARAMS)}>
|
||||||
{"Params" |> ReasonReact.string}
|
{"Params" |> ReasonReact.string}
|
||||||
|
@ -299,5 +360,6 @@ let make = (~distPlus: DistTypes.distPlus) => {
|
||||||
</div>
|
</div>
|
||||||
{state.showParams ? showAsForm(distPlus) : ReasonReact.null}
|
{state.showParams ? showAsForm(distPlus) : ReasonReact.null}
|
||||||
{state.showStats ? table(distPlus, x) : ReasonReact.null}
|
{state.showStats ? table(distPlus, x) : ReasonReact.null}
|
||||||
|
{state.showPercentiles ? percentiles(distPlus) : ReasonReact.null}
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
|
@ -7,6 +7,7 @@ type chartConfig = {
|
||||||
|
|
||||||
type state = {
|
type state = {
|
||||||
showStats: bool,
|
showStats: bool,
|
||||||
|
showPercentiles: bool,
|
||||||
showParams: bool,
|
showParams: bool,
|
||||||
distributions: list(chartConfig),
|
distributions: list(chartConfig),
|
||||||
};
|
};
|
||||||
|
@ -14,6 +15,7 @@ type state = {
|
||||||
type action =
|
type action =
|
||||||
| CHANGE_SHOW_STATS
|
| CHANGE_SHOW_STATS
|
||||||
| CHANGE_SHOW_PARAMS
|
| CHANGE_SHOW_PARAMS
|
||||||
|
| CHANGE_SHOW_PERCENTILES
|
||||||
| REMOVE_DIST(int)
|
| REMOVE_DIST(int)
|
||||||
| ADD_DIST
|
| ADD_DIST
|
||||||
| CHANGE_X_LOG(int)
|
| CHANGE_X_LOG(int)
|
||||||
|
@ -90,13 +92,18 @@ let reducer = (state: state, action: action) =>
|
||||||
}
|
}
|
||||||
| CHANGE_SHOW_STATS => {...state, showStats: !state.showStats}
|
| CHANGE_SHOW_STATS => {...state, showStats: !state.showStats}
|
||||||
| CHANGE_SHOW_PARAMS => {...state, showParams: !state.showParams}
|
| CHANGE_SHOW_PARAMS => {...state, showParams: !state.showParams}
|
||||||
|
| CHANGE_SHOW_PERCENTILES => {
|
||||||
|
...state,
|
||||||
|
showPercentiles: !state.showPercentiles,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let init = {
|
let init = {
|
||||||
showStats: false,
|
showStats: false,
|
||||||
showParams: false,
|
showParams: false,
|
||||||
|
showPercentiles: true,
|
||||||
distributions: [
|
distributions: [
|
||||||
{yLog: false, xLog: false, isCumulative: false, height: 2},
|
{yLog: false, xLog: false, isCumulative: false, height: 2},
|
||||||
{yLog: false, xLog: false, isCumulative: true, height: 1},
|
{yLog: false, xLog: false, isCumulative: true, height: 1},
|
||||||
],
|
],
|
||||||
};
|
};
|
|
@ -31,6 +31,7 @@ module type dist = {
|
||||||
let integral: (~cache: option(integral), t) => integral;
|
let integral: (~cache: option(integral), t) => integral;
|
||||||
let integralEndY: (~cache: option(integral), t) => float;
|
let integralEndY: (~cache: option(integral), t) => float;
|
||||||
let integralXtoY: (~cache: option(integral), float, t) => float;
|
let integralXtoY: (~cache: option(integral), float, t) => float;
|
||||||
|
let integralYtoX: (~cache: option(integral), float, t) => float;
|
||||||
};
|
};
|
||||||
|
|
||||||
module Dist = (T: dist) => {
|
module Dist = (T: dist) => {
|
||||||
|
@ -58,6 +59,7 @@ module Dist = (T: dist) => {
|
||||||
type t = T.integral;
|
type t = T.integral;
|
||||||
let get = T.integral;
|
let get = T.integral;
|
||||||
let xToY = T.integralXtoY;
|
let xToY = T.integralXtoY;
|
||||||
|
let yToX = T.integralYtoX;
|
||||||
let sum = T.integralEndY;
|
let sum = T.integralEndY;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,7 +107,7 @@ module Continuous = {
|
||||||
type integral = DistTypes.continuousShape;
|
type integral = DistTypes.continuousShape;
|
||||||
let minX = shapeFn(XYShape.minX);
|
let minX = shapeFn(XYShape.minX);
|
||||||
let maxX = shapeFn(XYShape.maxX);
|
let maxX = shapeFn(XYShape.maxX);
|
||||||
let toDiscreteProbabilityMass = t => 0.0;
|
let toDiscreteProbabilityMass = _ => 0.0;
|
||||||
let pointwiseFmap = (fn, t: t) =>
|
let pointwiseFmap = (fn, t: t) =>
|
||||||
t |> xyShape |> XYShape.pointwiseMap(fn) |> fromShape;
|
t |> xyShape |> XYShape.pointwiseMap(fn) |> fromShape;
|
||||||
let toShape = (t: t): DistTypes.shape => Continuous(t);
|
let toShape = (t: t): DistTypes.shape => Continuous(t);
|
||||||
|
@ -142,6 +144,8 @@ module Continuous = {
|
||||||
let integralEndY = (~cache, t) => t |> integral(~cache) |> lastY;
|
let integralEndY = (~cache, t) => t |> integral(~cache) |> lastY;
|
||||||
let integralXtoY = (~cache, f, t) =>
|
let integralXtoY = (~cache, f, t) =>
|
||||||
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f));
|
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findY(f));
|
||||||
|
let integralYtoX = (~cache, f, t) =>
|
||||||
|
t |> integral(~cache) |> shapeFn(CdfLibrary.Distribution.findX(f));
|
||||||
let toContinuous = t => Some(t);
|
let toContinuous = t => Some(t);
|
||||||
let toDiscrete = _ => None;
|
let toDiscrete = _ => None;
|
||||||
let toScaledContinuous = t => Some(t);
|
let toScaledContinuous = t => Some(t);
|
||||||
|
@ -176,12 +180,19 @@ module Discrete = {
|
||||||
|> E.O.default(0.0)
|
|> E.O.default(0.0)
|
||||||
|> DistTypes.MixedPoint.makeDiscrete;
|
|> DistTypes.MixedPoint.makeDiscrete;
|
||||||
};
|
};
|
||||||
|
|
||||||
// todo: This should use cache and/or same code as above. FindingY is more complex, should use interpolationType.
|
// todo: This should use cache and/or same code as above. FindingY is more complex, should use interpolationType.
|
||||||
let integralXtoY = (~cache, f, t) =>
|
let integralXtoY = (~cache, f, t) =>
|
||||||
t
|
t
|
||||||
|> integral(~cache)
|
|> integral(~cache)
|
||||||
|> Continuous.getShape
|
|> Continuous.getShape
|
||||||
|> CdfLibrary.Distribution.findY(f);
|
|> CdfLibrary.Distribution.findY(f);
|
||||||
|
|
||||||
|
let integralYtoX = (~cache, f, t) =>
|
||||||
|
t
|
||||||
|
|> integral(~cache)
|
||||||
|
|> Continuous.getShape
|
||||||
|
|> CdfLibrary.Distribution.findX(f);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -297,10 +308,18 @@ module Mixed = {
|
||||||
integral(~cache, t) |> Continuous.lastY;
|
integral(~cache, t) |> Continuous.lastY;
|
||||||
};
|
};
|
||||||
|
|
||||||
let integralXtoY = (~cache, f, {discrete, continuous} as t: t) => {
|
let integralXtoY = (~cache, f, t) => {
|
||||||
let cont = Continuous.T.Integral.xToY(~cache, f, continuous);
|
t
|
||||||
let discrete = Discrete.T.Integral.xToY(~cache, f, discrete);
|
|> integral(~cache)
|
||||||
scaleDiscreteFn(t, discrete) +. scaleContinuousFn(t, cont);
|
|> Continuous.getShape
|
||||||
|
|> CdfLibrary.Distribution.findX(f);
|
||||||
|
};
|
||||||
|
|
||||||
|
let integralYtoX = (~cache, f, t) => {
|
||||||
|
t
|
||||||
|
|> integral(~cache)
|
||||||
|
|> Continuous.getShape
|
||||||
|
|> CdfLibrary.Distribution.findY(f);
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: This functionality is kinda weird, because it seems to assume the cdf adds to 1.0 elsewhere, which wouldn't happen here.
|
// TODO: This functionality is kinda weird, because it seems to assume the cdf adds to 1.0 elsewhere, which wouldn't happen here.
|
||||||
|
@ -421,6 +440,16 @@ module Shape = {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
let integralYtoX = (~cache, f, t) => {
|
||||||
|
mapToAll(
|
||||||
|
t,
|
||||||
|
(
|
||||||
|
Mixed.T.Integral.yToX(~cache, f),
|
||||||
|
Discrete.T.Integral.yToX(~cache, f),
|
||||||
|
Continuous.T.Integral.yToX(~cache, f),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
};
|
||||||
let maxX = (t: t) =>
|
let maxX = (t: t) =>
|
||||||
mapToAll(t, (Mixed.T.maxX, Discrete.T.maxX, Continuous.T.maxX));
|
mapToAll(t, (Mixed.T.maxX, Discrete.T.maxX, Continuous.T.maxX));
|
||||||
let pointwiseFmap = (fn, t: t) =>
|
let pointwiseFmap = (fn, t: t) =>
|
||||||
|
@ -543,6 +572,11 @@ module DistPlus = {
|
||||||
Shape.T.Integral.xToY(~cache=Some(t.integralCache), f, toShape(t))
|
Shape.T.Integral.xToY(~cache=Some(t.integralCache), f, toShape(t))
|
||||||
|> domainIncludedProbabilityMassAdjustment(t);
|
|> domainIncludedProbabilityMassAdjustment(t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: This part is broken when there is a limit, if this is supposed to be taken into account.
|
||||||
|
let integralYtoX = (~cache as _, f, t: t) => {
|
||||||
|
Shape.T.Integral.yToX(~cache=Some(t.integralCache), f, toShape(t));
|
||||||
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user