Basic stats table. Unformatted
This commit is contained in:
parent
99b9bc6b1e
commit
64fbe05f3a
|
@ -1,8 +1,12 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import type { Spec } from "vega";
|
import type { Spec } from "vega";
|
||||||
import type { Distribution } from "@quri/squiggle-lang";
|
import {
|
||||||
import { distributionErrorToString } from "@quri/squiggle-lang";
|
Distribution,
|
||||||
|
result,
|
||||||
|
distributionError,
|
||||||
|
distributionErrorToString,
|
||||||
|
} from "@quri/squiggle-lang";
|
||||||
import { createClassFromSpec } from "react-vega";
|
import { createClassFromSpec } from "react-vega";
|
||||||
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
||||||
import { ErrorBox } from "./ErrorBox";
|
import { ErrorBox } from "./ErrorBox";
|
||||||
|
@ -16,30 +20,101 @@ type DistributionChartProps = {
|
||||||
distribution: Distribution;
|
distribution: Distribution;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
/** Whether to show a summary of means, stdev, percentiles etc */
|
||||||
|
showSummary: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DistributionChart: React.FC<DistributionChartProps> = ({
|
export const DistributionChart: React.FC<DistributionChartProps> = ({
|
||||||
distribution,
|
distribution,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
showSummary,
|
||||||
}: DistributionChartProps) => {
|
}: DistributionChartProps) => {
|
||||||
let shape = distribution.pointSet();
|
let shape = distribution.pointSet();
|
||||||
if (shape.tag === "Ok") {
|
if (shape.tag === "Ok") {
|
||||||
let widthProp = width ? width - 20 : undefined;
|
let widthProp = width ? width - 20 : undefined;
|
||||||
var result = (
|
return (
|
||||||
|
<>
|
||||||
<SquiggleVegaChart
|
<SquiggleVegaChart
|
||||||
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
||||||
width={widthProp}
|
width={widthProp}
|
||||||
height={height}
|
height={height}
|
||||||
actions={false}
|
actions={false}
|
||||||
/>
|
/>
|
||||||
|
{showSummary ? <SummaryTable distribution={distribution} /> : <></>}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
var result = (
|
return (
|
||||||
<ErrorBox heading="Distribution Error">
|
<ErrorBox heading="Distribution Error">
|
||||||
{distributionErrorToString(shape.value)}
|
{distributionErrorToString(shape.value)}
|
||||||
</ErrorBox>
|
</ErrorBox>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return result;
|
};
|
||||||
|
|
||||||
|
type SummaryTableProps = {
|
||||||
|
distribution: Distribution;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Table = styled.table``;
|
||||||
|
const Row = styled.tr``;
|
||||||
|
const Cell = styled.td``;
|
||||||
|
const TableHeader = styled.th``;
|
||||||
|
|
||||||
|
const SummaryTable: React.FC<SummaryTableProps> = ({
|
||||||
|
distribution,
|
||||||
|
}: SummaryTableProps) => {
|
||||||
|
let mean = distribution.mean();
|
||||||
|
let median = distribution.inv(0.5);
|
||||||
|
let p5 = distribution.inv(0.05);
|
||||||
|
let p10 = distribution.inv(0.1);
|
||||||
|
let Q1 = distribution.inv(0.25);
|
||||||
|
let Q3 = distribution.inv(0.75);
|
||||||
|
let p90 = distribution.inv(0.9);
|
||||||
|
let p95 = distribution.inv(0.95);
|
||||||
|
let unwrapResult = (
|
||||||
|
x: result<number, distributionError>
|
||||||
|
): React.ReactNode => {
|
||||||
|
if (x.tag === "Ok") {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{Intl.NumberFormat("en-US", { maximumSignificantDigits: 3 }).format(
|
||||||
|
x.value
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<ErrorBox heading="Distribution Error">
|
||||||
|
{distributionErrorToString(x.value)}
|
||||||
|
</ErrorBox>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table>
|
||||||
|
<Row>
|
||||||
|
<TableHeader>{"Mean"}</TableHeader>
|
||||||
|
<TableHeader>{"5%"}</TableHeader>
|
||||||
|
<TableHeader>{"10%"}</TableHeader>
|
||||||
|
<TableHeader>{"Q1 (25%)"}</TableHeader>
|
||||||
|
<TableHeader>{"Median (50%)"}</TableHeader>
|
||||||
|
<TableHeader>{"Q3 (75%)"}</TableHeader>
|
||||||
|
<TableHeader>{"90%"}</TableHeader>
|
||||||
|
<TableHeader>{"95%"}</TableHeader>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Cell>{unwrapResult(mean)}</Cell>
|
||||||
|
<Cell>{unwrapResult(p5)}</Cell>
|
||||||
|
<Cell>{unwrapResult(p10)}</Cell>
|
||||||
|
<Cell>{unwrapResult(Q1)}</Cell>
|
||||||
|
<Cell>{unwrapResult(median)}</Cell>
|
||||||
|
<Cell>{unwrapResult(Q3)}</Cell>
|
||||||
|
<Cell>{unwrapResult(p90)}</Cell>
|
||||||
|
<Cell>{unwrapResult(p95)}</Cell>
|
||||||
|
</Row>
|
||||||
|
</Table>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,6 +61,7 @@ export const FunctionChart: React.FC<{
|
||||||
distribution={mouseItem.value}
|
distribution={mouseItem.value}
|
||||||
width={400}
|
width={400}
|
||||||
height={140}
|
height={140}
|
||||||
|
showSummary={false}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
|
|
|
@ -54,12 +54,15 @@ export interface SquiggleItemProps {
|
||||||
expression: squiggleExpression;
|
expression: squiggleExpression;
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
|
/** Whether to show a summary of statistics for distributions */
|
||||||
|
showSummary: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
expression,
|
expression,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
showSummary,
|
||||||
}: SquiggleItemProps) => {
|
}: SquiggleItemProps) => {
|
||||||
switch (expression.tag) {
|
switch (expression.tag) {
|
||||||
case "number":
|
case "number":
|
||||||
|
@ -83,6 +86,7 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
distribution={expression.value}
|
distribution={expression.value}
|
||||||
height={height}
|
height={height}
|
||||||
width={width}
|
width={width}
|
||||||
|
showSummary={showSummary}
|
||||||
/>
|
/>
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
|
@ -105,7 +109,12 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
return (
|
return (
|
||||||
<VariableBox heading="Array">
|
<VariableBox heading="Array">
|
||||||
{expression.value.map((r) => (
|
{expression.value.map((r) => (
|
||||||
<SquiggleItem expression={r} width={width - 20} height={50} />
|
<SquiggleItem
|
||||||
|
expression={r}
|
||||||
|
width={width - 20}
|
||||||
|
height={50}
|
||||||
|
showSummary={showSummary}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
|
@ -115,17 +124,16 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||||
{Object.entries(expression.value).map(([key, r]) => (
|
{Object.entries(expression.value).map(([key, r]) => (
|
||||||
<>
|
<>
|
||||||
<RecordKeyHeader>{key}</RecordKeyHeader>
|
<RecordKeyHeader>{key}</RecordKeyHeader>
|
||||||
<SquiggleItem expression={r} width={width - 20} height={50} />
|
<SquiggleItem
|
||||||
|
expression={r}
|
||||||
|
width={width - 20}
|
||||||
|
height={50}
|
||||||
|
showSummary={showSummary}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
))}
|
))}
|
||||||
</VariableBox>
|
</VariableBox>
|
||||||
);
|
);
|
||||||
default:
|
|
||||||
return (
|
|
||||||
<ErrorBox heading="No Viewer">
|
|
||||||
{"We don't currently have a working viewer for record types."}
|
|
||||||
</ErrorBox>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -155,6 +163,8 @@ export interface SquiggleChartProps {
|
||||||
bindings?: bindings;
|
bindings?: bindings;
|
||||||
/** JS imported parameters */
|
/** JS imported parameters */
|
||||||
jsImports?: jsImports;
|
jsImports?: jsImports;
|
||||||
|
/** Whether to show a summary of the distirbution */
|
||||||
|
showSummary?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ChartWrapper = styled.div`
|
const ChartWrapper = styled.div`
|
||||||
|
@ -172,6 +182,7 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
bindings = defaultBindings,
|
bindings = defaultBindings,
|
||||||
jsImports = defaultImports,
|
jsImports = defaultImports,
|
||||||
width = NaN,
|
width = NaN,
|
||||||
|
showSummary = false,
|
||||||
}: SquiggleChartProps) => {
|
}: SquiggleChartProps) => {
|
||||||
let samplingInputs: samplingParams = {
|
let samplingInputs: samplingParams = {
|
||||||
sampleCount: sampleCount,
|
sampleCount: sampleCount,
|
||||||
|
@ -188,7 +199,12 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
||||||
let expression = expressionResult.value;
|
let expression = expressionResult.value;
|
||||||
onChange(expression);
|
onChange(expression);
|
||||||
internal = (
|
internal = (
|
||||||
<SquiggleItem expression={expression} width={width} height={height} />
|
<SquiggleItem
|
||||||
|
expression={expression}
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
showSummary={showSummary}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
internal = (
|
internal = (
|
||||||
|
|
|
@ -11,6 +11,7 @@ export {
|
||||||
makeSampleSetDist,
|
makeSampleSetDist,
|
||||||
errorValueToString,
|
errorValueToString,
|
||||||
distributionErrorToString,
|
distributionErrorToString,
|
||||||
|
distributionError,
|
||||||
} from "../rescript/TypescriptInterface.gen";
|
} from "../rescript/TypescriptInterface.gen";
|
||||||
export type {
|
export type {
|
||||||
samplingParams,
|
samplingParams,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user