Basic stats table. Unformatted
This commit is contained in:
parent
99b9bc6b1e
commit
64fbe05f3a
|
@ -1,8 +1,12 @@
|
|||
import * as React from "react";
|
||||
import _ from "lodash";
|
||||
import type { Spec } from "vega";
|
||||
import type { Distribution } from "@quri/squiggle-lang";
|
||||
import { distributionErrorToString } from "@quri/squiggle-lang";
|
||||
import {
|
||||
Distribution,
|
||||
result,
|
||||
distributionError,
|
||||
distributionErrorToString,
|
||||
} from "@quri/squiggle-lang";
|
||||
import { createClassFromSpec } from "react-vega";
|
||||
import * as chartSpecification from "../vega-specs/spec-distributions.json";
|
||||
import { ErrorBox } from "./ErrorBox";
|
||||
|
@ -16,30 +20,101 @@ type DistributionChartProps = {
|
|||
distribution: Distribution;
|
||||
width: number;
|
||||
height: number;
|
||||
/** Whether to show a summary of means, stdev, percentiles etc */
|
||||
showSummary: boolean;
|
||||
};
|
||||
|
||||
export const DistributionChart: React.FC<DistributionChartProps> = ({
|
||||
distribution,
|
||||
width,
|
||||
height,
|
||||
showSummary,
|
||||
}: DistributionChartProps) => {
|
||||
let shape = distribution.pointSet();
|
||||
if (shape.tag === "Ok") {
|
||||
let widthProp = width ? width - 20 : undefined;
|
||||
var result = (
|
||||
return (
|
||||
<>
|
||||
<SquiggleVegaChart
|
||||
data={{ con: shape.value.continuous, dis: shape.value.discrete }}
|
||||
width={widthProp}
|
||||
height={height}
|
||||
actions={false}
|
||||
/>
|
||||
{showSummary ? <SummaryTable distribution={distribution} /> : <></>}
|
||||
</>
|
||||
);
|
||||
} else {
|
||||
var result = (
|
||||
return (
|
||||
<ErrorBox heading="Distribution Error">
|
||||
{distributionErrorToString(shape.value)}
|
||||
</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}
|
||||
width={400}
|
||||
height={140}
|
||||
showSummary={false}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
|
|
|
@ -54,12 +54,15 @@ export interface SquiggleItemProps {
|
|||
expression: squiggleExpression;
|
||||
width: number;
|
||||
height: number;
|
||||
/** Whether to show a summary of statistics for distributions */
|
||||
showSummary: boolean;
|
||||
}
|
||||
|
||||
const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
||||
expression,
|
||||
width,
|
||||
height,
|
||||
showSummary,
|
||||
}: SquiggleItemProps) => {
|
||||
switch (expression.tag) {
|
||||
case "number":
|
||||
|
@ -83,6 +86,7 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
distribution={expression.value}
|
||||
height={height}
|
||||
width={width}
|
||||
showSummary={showSummary}
|
||||
/>
|
||||
</VariableBox>
|
||||
);
|
||||
|
@ -105,7 +109,12 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
return (
|
||||
<VariableBox heading="Array">
|
||||
{expression.value.map((r) => (
|
||||
<SquiggleItem expression={r} width={width - 20} height={50} />
|
||||
<SquiggleItem
|
||||
expression={r}
|
||||
width={width - 20}
|
||||
height={50}
|
||||
showSummary={showSummary}
|
||||
/>
|
||||
))}
|
||||
</VariableBox>
|
||||
);
|
||||
|
@ -115,17 +124,16 @@ const SquiggleItem: React.FC<SquiggleItemProps> = ({
|
|||
{Object.entries(expression.value).map(([key, r]) => (
|
||||
<>
|
||||
<RecordKeyHeader>{key}</RecordKeyHeader>
|
||||
<SquiggleItem expression={r} width={width - 20} height={50} />
|
||||
<SquiggleItem
|
||||
expression={r}
|
||||
width={width - 20}
|
||||
height={50}
|
||||
showSummary={showSummary}
|
||||
/>
|
||||
</>
|
||||
))}
|
||||
</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;
|
||||
/** JS imported parameters */
|
||||
jsImports?: jsImports;
|
||||
/** Whether to show a summary of the distirbution */
|
||||
showSummary?: boolean;
|
||||
}
|
||||
|
||||
const ChartWrapper = styled.div`
|
||||
|
@ -172,6 +182,7 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
|||
bindings = defaultBindings,
|
||||
jsImports = defaultImports,
|
||||
width = NaN,
|
||||
showSummary = false,
|
||||
}: SquiggleChartProps) => {
|
||||
let samplingInputs: samplingParams = {
|
||||
sampleCount: sampleCount,
|
||||
|
@ -188,7 +199,12 @@ export const SquiggleChart: React.FC<SquiggleChartProps> = ({
|
|||
let expression = expressionResult.value;
|
||||
onChange(expression);
|
||||
internal = (
|
||||
<SquiggleItem expression={expression} width={width} height={height} />
|
||||
<SquiggleItem
|
||||
expression={expression}
|
||||
width={width}
|
||||
height={height}
|
||||
showSummary={showSummary}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
internal = (
|
||||
|
|
|
@ -11,6 +11,7 @@ export {
|
|||
makeSampleSetDist,
|
||||
errorValueToString,
|
||||
distributionErrorToString,
|
||||
distributionError,
|
||||
} from "../rescript/TypescriptInterface.gen";
|
||||
export type {
|
||||
samplingParams,
|
||||
|
|
Loading…
Reference in New Issue
Block a user