Add Discrete chart viewer

This commit is contained in:
Sam Nolan 2022-02-13 20:20:53 +11:00
parent 974ca2335e
commit 3d3450d281
4 changed files with 108 additions and 25 deletions

View File

@ -12,10 +12,12 @@
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.4.0",
"@types/lodash": "^4.14.178",
"@types/node": "^17.0.16",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"cross-env": "^7.0.3",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",
@ -11544,6 +11546,11 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
},
"node_modules/@types/lodash": {
"version": "4.14.178",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
},
"node_modules/@types/mdast": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",
@ -40916,6 +40923,11 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4="
},
"@types/lodash": {
"version": "4.14.178",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
},
"@types/mdast": {
"version": "3.0.10",
"resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz",

View File

@ -8,10 +8,12 @@
"@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.4.0",
"@types/lodash": "^4.14.178",
"@types/node": "^17.0.16",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.11",
"cross-env": "^7.0.3",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-scripts": "5.0.0",

View File

@ -1,5 +1,6 @@
import * as React from 'react';
import * as PropTypes from 'prop-types';
import * as _ from 'lodash';
import './button.css';
import type { LinearScale, Spec } from 'vega';
import { run } from '@squiggle/squiggle-lang';
@ -11,16 +12,24 @@ let scales : LinearScale[] = [{
"range": "width",
"zero": false,
"nice": false,
"domain":
{"data": "table", "field": "x"}
"domain": {
"fields": [
{ "data": "con", "field": "x"},
{ "data": "dis", "field": "x"}
]
}
}, {
"name": "yscale",
"type": "linear",
"range": "height",
"nice": true,
"zero": true,
"domain":
{"data": "table", "field": "y"}
"domain": {
"fields": [
{ "data": "con", "field": "y"},
{ "data": "dis", "field": "y"}
]
}
}
]
@ -31,7 +40,7 @@ let specification : Spec = {
"width": 500,
"height": 200,
"padding": 5,
"data": [{"name": "table"}],
"data": [{"name": "con"}, {"name": "dis"}],
"signals": [
{
@ -52,7 +61,7 @@ let specification : Spec = {
"marks": [
{
"type": "area",
"from": {"data": "table"},
"from": {"data": "con"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "x"},
@ -68,22 +77,37 @@ let specification : Spec = {
"fillOpacity": {"value": 1}
}
}
},
{
"type": "rect",
"from": {"data": "dis"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "x"},
"y": {"scale": "yscale", "field": "y"},
"y2": {"scale": "yscale", "value": 0},
"width": {"value": 1}
}
}
},
{
"type": "symbol",
"from": {"data": "dis"},
"encode": {
"enter": {
"shape": {"value": "circle"},
"x": {"scale": "xscale", "field": "x"},
"y": {"scale": "yscale", "field": "y"},
"width": {"value": 5},
"tooltip": {"signal": "datum.y"},
}
}
}
]
};
let SquiggleVegaChart = createClassFromSpec({'spec': specification});
function zip<T>(a: Array<T>, b: Array<T>): Array<Array<T>>{
return a.map(function(e, i) {
return [e, b[i]];
})
}
function zip3<T>(a: Array<T>, b: Array<T>, c: Array<T>): Array<Array<T>>{
return a.map(function(e, i) {
return [e, b[i], c[i]];
})
}
/**
* Primary UI component for user interaction
*/
@ -106,11 +130,11 @@ export const SquiggleChart = ({ squiggleString }: { squiggleString: string}) =>
return total / totalY;
})
console.log(cdf)
let values = zip3(cdf, xyShape.xs, xyShape.ys).map(([c, x, y ]) => ({cdf: (c * 100).toFixed(2) + "%", x: x, y: y}));
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x, y ]) => ({cdf: (c * 100).toFixed(2) + "%", x: x, y: y}));
return (
<SquiggleVegaChart
data={{"table": values}}
data={{"con": values}}
/>
);
}
@ -122,23 +146,63 @@ export const SquiggleChart = ({ squiggleString }: { squiggleString: string}) =>
total += y;
return total / totalY;
})
let values = zip3(cdf, xyShape.xs, xyShape.ys).map(([c, x,y]) => ({cdf: (c * 100).toFixed(2) + "%", x: x, y: y}));
let values = _.zip(cdf, xyShape.xs, xyShape.ys).map(([c, x,y]) => ({cdf: (c * 100).toFixed(2) + "%", x: x, y: y}));
return (
<SquiggleVegaChart
data={{"name": "table", "values": values}}
data={{"dis": values}}
/>
);
}
else if(shape.tag === "Mixed"){
console.log(shape.value.integralSumCache)
console.log(shape.value.integralCache)
let xyShape = shape.value.continuous.xyShape;
let values = zip(xyShape.xs, xyShape.ys).map(([x,y]) => ({x: x, y: y}));
console.log(shape)
console.log(shape.value.continuous.integralSumCache)
let discreteShape = shape.value.discrete.xyShape;
let totalDiscrete = discreteShape.ys.reduce((a, b) => a + b);
let discretePoints = _.zip(discreteShape.xs, discreteShape.ys);
let continuousShape = shape.value.continuous.xyShape;
let continuousPoints = _.zip(continuousShape.xs, continuousShape.ys);
interface labeledPoint {
x: number,
y: number,
type: "discrete" | "continuous"
};
let markedDisPoints : labeledPoint[] = discretePoints.map(([x,y]) => ({x: x, y: y, type: "discrete"}))
let markedConPoints : labeledPoint[] = continuousPoints.map(([x,y]) => ({x: x, y: y, type: "continuous"}))
let sortedPoints = _.sortBy(markedDisPoints.concat(markedConPoints), 'x')
let totalContinuous = 1 - totalDiscrete;
let totalY = continuousShape.ys.reduce((a:number, b:number) => a + b);
let total = 0;
let cdf = sortedPoints.map((point: labeledPoint) => {
if(point.type == "discrete") {
total += point.y;
return total;
}
else if (point.type == "continuous") {
total += point.y / totalY * totalContinuous;
return total;
}
});
interface cdfLabeledPoint {
cdf: string,
x: number,
y: number,
type: "discrete" | "continuous"
}
let cdfLabeledPoint : cdfLabeledPoint[] = _.zipWith(cdf, sortedPoints, (c: number, point: labeledPoint) => ({...point, cdf: (c * 100).toFixed(2) + "%"}))
let continuousValues = cdfLabeledPoint.filter(x => x.type == "continuous")
let discreteValues = cdfLabeledPoint.filter(x => x.type == "discrete")
return (
<SquiggleVegaChart
data={{"name": "table", "values": values}}
data={{"con": continuousValues, "dis": discreteValues}}
/>
);
}

View File

@ -3085,6 +3085,11 @@
"resolved" "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz"
"version" "0.0.29"
"@types/lodash@^4.14.178":
"integrity" "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
"resolved" "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz"
"version" "4.14.178"
"@types/mdast@^3.0.0":
"integrity" "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA=="
"resolved" "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz"