Minor cleanup of mean and variance

This commit is contained in:
Ozzie Gooen 2020-04-19 21:04:50 +01:00
parent 0fd5e2dcdb
commit f247f65478
4 changed files with 121 additions and 110 deletions

View File

@ -194,10 +194,10 @@ describe("Shape", () => {
0.9,
);
makeTest("integralEndY", T.Integral.sum(~cache=None, discrete), 1.0);
makeTest("mean", T.getMean(discrete), 3.9);
makeTest("mean", T.mean(discrete), 3.9);
makeTestCloseEquality(
"variance",
T.getVariance(discrete),
T.variance(discrete),
5.89,
~digits=7,
);
@ -393,25 +393,25 @@ describe("Shape", () => {
makeTestCloseEquality(
"Mean of a normal",
T.getMean(normalShape),
T.mean(normalShape),
mean,
~digits=2,
);
makeTestCloseEquality(
"Variance of a normal",
T.getVariance(normalShape),
T.variance(normalShape),
variance,
~digits=1,
);
makeTestCloseEquality(
"Mean of a lognormal",
T.getMean(lognormalShape),
T.mean(lognormalShape),
mean,
~digits=2,
);
makeTestCloseEquality(
"Variance of a lognormal",
T.getVariance(lognormalShape),
T.variance(lognormalShape),
variance,
~digits=0,
);

View File

@ -124,73 +124,87 @@ let table = (distPlus, x) => {
</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>
<td className="px-4 py-2 border">
{distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.999)
|> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.9999)
|> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.99999)
|> showFloat}
</td>
</tr>
</tbody>
</table>;
<div>
<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>
<td className="px-4 py-2"> {"99.999" |> 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>
<td className="px-4 py-2 border">
{distPlus
|> Distributions.DistPlus.T.Integral.yToX(~cache=None, 0.99999)
|> showFloat}
</td>
</tr>
</tbody>
</table>
<table className="table-auto text-sm">
<thead>
<tr>
<td className="px-4 py-2"> {"mean" |> ReasonReact.string} </td>
<td className="px-4 py-2">
{"standard deviation" |> ReasonReact.string}
</td>
<td className="px-4 py-2"> {"variance" |> ReasonReact.string} </td>
</tr>
</thead>
<tbody>
<tr>
<td className="px-4 py-2 border">
{distPlus |> Distributions.DistPlus.T.mean |> showFloat}
</td>
<td className="px-4 py-2 border">
{distPlus |> Distributions.DistPlus.T.variance |> showFloat}
</td>
</tr>
</tbody>
</table>
</div>;
};
let adjustBoth = discreteProbabilityMass => {

View File

@ -18,8 +18,8 @@ module type dist = {
let integralXtoY: (~cache: option(integral), float, t) => float;
let integralYtoX: (~cache: option(integral), float, t) => float;
let getMean: t => float;
let getVariance: t => float;
let mean: t => float;
let variance: t => float;
};
module Dist = (T: dist) => {
@ -38,8 +38,8 @@ module Dist = (T: dist) => {
let toDiscrete = T.toDiscrete;
let toScaledContinuous = T.toScaledContinuous;
let toScaledDiscrete = T.toScaledDiscrete;
let getMean = T.getMean;
let getVariance = T.getVariance;
let mean = T.mean;
let variance = T.variance;
// TODO: Move this to each class, have use integral to produce integral in DistPlus class.
let scaleBy = (~scale=1.0, t: t) => t |> mapY((r: float) => r *. scale);
@ -141,7 +141,7 @@ module Continuous = {
let toScaledContinuous = t => Some(t);
let toScaledDiscrete = _ => None;
let getMean = (t: t) => {
let mean = (t: t) => {
let indefiniteIntegralStepwise = (p, h1) => h1 *. p ** 2.0 /. 2.0;
let indefiniteIntegralLinear = (p, a, b) =>
a *. p ** 2.0 /. 2.0 +. b *. p ** 3.0 /. 3.0;
@ -151,10 +151,10 @@ module Continuous = {
t,
);
};
let getVariance = (t: t): float =>
let variance = (t: t): float =>
XYShape.Analysis.getVarianceDangerously(
t,
getMean,
mean,
XYShape.Analysis.getMeanOfSquaresContinuousShape,
);
});
@ -229,12 +229,12 @@ module Discrete = {
|> Continuous.getShape
|> XYShape.YtoX.linear(f);
let getMean = (t: t): float =>
let mean = (t: t): float =>
E.A.reducei(t.xs, 0.0, (acc, x, i) => acc +. x *. t.ys[i]);
let getVariance = (t: t): float => {
let variance = (t: t): float => {
let getMeanOfSquares = t =>
getMean(XYShape.Analysis.squareXYShape(t));
XYShape.Analysis.getVarianceDangerously(t, getMean, getMeanOfSquares);
mean(XYShape.Analysis.squareXYShape(t));
XYShape.Analysis.getVarianceDangerously(t, mean, getMeanOfSquares);
};
});
};
@ -408,36 +408,36 @@ module Mixed = {
};
};
let getMean = (t: t): float => {
let mean = (t: t): float => {
let discreteProbabilityMassFraction =
t.discreteProbabilityMassFraction;
switch (discreteProbabilityMassFraction) {
| 1.0 => Discrete.T.getMean(t.discrete)
| 0.0 => Continuous.T.getMean(t.continuous)
| 1.0 => Discrete.T.mean(t.discrete)
| 0.0 => Continuous.T.mean(t.continuous)
| _ =>
Discrete.T.getMean(t.discrete)
Discrete.T.mean(t.discrete)
*. discreteProbabilityMassFraction
+. Continuous.T.getMean(t.continuous)
+. Continuous.T.mean(t.continuous)
*. (1.0 -. discreteProbabilityMassFraction)
};
};
let getVariance = (t: t): float => {
let variance = (t: t): float => {
let discreteProbabilityMassFraction =
t.discreteProbabilityMassFraction;
let getMeanOfSquares = (t: t) => {
Discrete.T.getMean(XYShape.Analysis.squareXYShape(t.discrete))
Discrete.T.mean(XYShape.Analysis.squareXYShape(t.discrete))
*. t.discreteProbabilityMassFraction
+. XYShape.Analysis.getMeanOfSquaresContinuousShape(t.continuous)
*. (1.0 -. t.discreteProbabilityMassFraction);
};
switch (discreteProbabilityMassFraction) {
| 1.0 => Discrete.T.getVariance(t.discrete)
| 0.0 => Continuous.T.getVariance(t.continuous)
| 1.0 => Discrete.T.variance(t.discrete)
| 0.0 => Continuous.T.variance(t.continuous)
| _ =>
XYShape.Analysis.getVarianceDangerously(
t,
getMean,
mean,
getMeanOfSquares,
)
};
@ -547,18 +547,18 @@ module Shape = {
Continuous.T.mapY(fn),
));
let getMean = (t: t): float =>
let mean = (t: t): float =>
switch (t) {
| Mixed(m) => Mixed.T.getMean(m)
| Discrete(m) => Discrete.T.getMean(m)
| Continuous(m) => Continuous.T.getMean(m)
| Mixed(m) => Mixed.T.mean(m)
| Discrete(m) => Discrete.T.mean(m)
| Continuous(m) => Continuous.T.mean(m)
};
let getVariance = (t: t): float =>
let variance = (t: t): float =>
switch (t) {
| Mixed(m) => Mixed.T.getVariance(m)
| Discrete(m) => Discrete.T.getVariance(m)
| Continuous(m) => Continuous.T.getVariance(m)
| Mixed(m) => Mixed.T.variance(m)
| Discrete(m) => Discrete.T.variance(m)
| Continuous(m) => Continuous.T.variance(m)
};
});
};
@ -674,8 +674,8 @@ module DistPlus = {
let integralYtoX = (~cache as _, f, t: t) => {
Shape.T.Integral.yToX(~cache=Some(t.integralCache), f, toShape(t));
};
let getMean = (t: t) => Shape.T.getMean(t.shape);
let getVariance = (t: t) => Shape.T.getVariance(t.shape);
let mean = (t: t) => Shape.T.mean(t.shape);
let variance = (t: t) => Shape.T.variance(t.shape);
});
};

View File

@ -347,14 +347,11 @@ module Analysis = {
};
let getVarianceDangerously =
(t: 't, getMean: 't => float, getMeanOfSquares: 't => float): float => {
let meanSquared = getMean(t) ** 2.0;
(t: 't, mean: 't => float, getMeanOfSquares: 't => float): float => {
let meanSquared = mean(t) ** 2.0;
let meanOfSquares = getMeanOfSquares(t);
meanOfSquares -. meanSquared;
};
let squareXYShape = (t): DistTypes.xyShape => {
...t,
xs: E.A.fmap(x => x ** 2.0, t.xs),
};
let squareXYShape = T.mapX(x => x ** 2.0)
};