Skip to content

Commit

Permalink
Merge pull request #75 from conglei/conglei-stats-xychart
Browse files Browse the repository at this point in the history
added stats charts in xy-chart
  • Loading branch information
williaster authored Nov 16, 2017
2 parents 6174372 + eaf230d commit f5d4f42
Show file tree
Hide file tree
Showing 12 changed files with 650 additions and 2 deletions.
270 changes: 270 additions & 0 deletions packages/demo/examples/01-xy-chart/StatsSeriesExample.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
/* eslint react/prop-types: 0 */
import React from 'react';

import {
XAxis,
YAxis,
BoxPlotSeries,
ViolinPlotSeries,
PatternLines,
LinearGradient,
theme,
} from '@data-ui/xy-chart';

import ResponsiveXYChart from './ResponsiveXYChart';

import { statsData } from './data';

const { colors } = theme;

function renderViolinPlotTooltip({ datum, color }) {
const { x, y, binData } = datum;
const label = x || y;
return (
<div>
<div>
<strong style={{ color }}>{label}</strong>
</div>
<div>
<strong style={{ color }}>Bin Number </strong>
{binData.length}
</div>
</div>
);
}
function renderBoxPlotTooltip({ datum, color }) {
const {
x,
y,
min,
max,
median,
firstQuartile,
thirdQuartile,
outliers,
} = datum;

const label = x || y;
return (
<div>
<div>
<strong style={{ color }}>{label}</strong>
</div>
<div>
<strong style={{ color }}>Min </strong>
{min && min.toFixed ? min.toFixed(2) : min}
</div>
<div>
<strong style={{ color }}>Max </strong>
{max && max.toFixed ? max.toFixed(2) : max}
</div>
<div>
<strong style={{ color }}>Median </strong>
{median && median.toFixed ? median.toFixed(2) : median}
</div>
<div>
<strong style={{ color }}>First Quartile </strong>
{firstQuartile && firstQuartile.toFixed ? firstQuartile.toFixed(2) : firstQuartile}
</div>
<div>
<strong style={{ color }}>Third Quartile </strong>
{thirdQuartile && thirdQuartile.toFixed ? thirdQuartile.toFixed(2) : thirdQuartile}
</div>
<div>
<strong style={{ color }}>Outliers Number </strong>
{outliers.length}
</div>
</div>
);
}

export function SimpleBoxPlotSeriesExample() {
const boxPlotData = statsData.map(s => s.boxPlot);
const values = boxPlotData.reduce((r, e) => r.push(e.min, e.max, ...e.outliers) && r, []);
const minYValue = Math.min(...values);
const maxYValue = Math.max(...values);
const yDomain = [minYValue - (0.1 * Math.abs(minYValue)),
maxYValue + (0.1 * Math.abs(minYValue))];
return (
<ResponsiveXYChart
theme={{}}
ariaLabel="Required label"
xScale={{
type: 'band',
paddingInner: 0.15,
paddingOuter: 0.3,
}}
yScale={{ type: 'linear',
domain: yDomain,
}}
renderTooltip={renderBoxPlotTooltip}
showYGrid
>
<LinearGradient
id="aqua_lightaqua_gradient"
from="#99e9f2"
to="#c5f6fa"
/>
<YAxis numTicks={4} />
<BoxPlotSeries
data={boxPlotData}
fill="url(#aqua_lightaqua_gradient)"
stroke="#22b8cf"
strokeWidth={1.5}
/>
<XAxis />
</ResponsiveXYChart>
);
}

export function SingleBoxPlotSeriesExample() {
const singleStats = [statsData[0]];
const boxPlotData = singleStats.map((s) => {
const { boxPlot } = s;
const { x, ...rest } = boxPlot;
return {
y: x,
...rest,
};
});
const values = boxPlotData.reduce((r, e) => r.push(e.min, e.max, ...e.outliers) && r, []);
const minXValue = Math.min(...values);
const maxXValue = Math.max(...values);
const xDomain = [minXValue - (0.1 * Math.abs(minXValue)),
maxXValue + (0.1 * Math.abs(maxXValue))];
return (
<ResponsiveXYChart
theme={{}}
ariaLabel="Required label"
yScale={{
type: 'band',
paddingInner: 0.15,
paddingOuter: 0.3,
}}
xScale={{ type: 'linear',
domain: xDomain,
}}
renderTooltip={renderBoxPlotTooltip}
showYGrid
>
<LinearGradient
id="aqua_lightaqua_gradient"
from="#99e9f2"
to="#c5f6fa"
/>
<BoxPlotSeries
data={boxPlotData}
fill="url(#aqua_lightaqua_gradient)"
stroke="#22b8cf"
strokeWidth={1.5}
horizontal
/>
<XAxis />
</ResponsiveXYChart>
);
}

export function HorizontalBoxPlotViolinPlotSeriesExample() {
const boxPlotData = statsData.map((s) => {
const { boxPlot } = s;
const { x, ...rest } = boxPlot;
return {
y: x,
...rest,
};
});
const violinData = statsData.map(s => ({ y: s.boxPlot.x, binData: s.binData }));
const values = boxPlotData.reduce((r, e) => r.push(e.min, e.max, ...e.outliers) && r, []);
const minXValue = Math.min(...values);
const maxXValue = Math.max(...values);
const xDomain = [minXValue - (0.1 * Math.abs(minXValue)),
maxXValue + (0.1 * Math.abs(maxXValue))];
return (
<ResponsiveXYChart
theme={{}}
ariaLabel="Required label"
yScale={{
type: 'band',
paddingInner: 0.15,
paddingOuter: 0.3,
}}
xScale={{ type: 'linear',
domain: xDomain,
}}
renderTooltip={renderBoxPlotTooltip}
showYGrid
>
<PatternLines
id="vViolinLines"
height={3}
width={3}
stroke="#ced4da"
strokeWidth={1}
fill="rgba(0,0,0,0.3)"
/>
<YAxis numTicks={4} />
<ViolinPlotSeries
data={violinData}
fill="url(#vViolinLines)"
stroke="#22b8cf"
strokeWidth={0.5}
horizontal
disableMouseEvents
/>
<BoxPlotSeries
data={boxPlotData}
fill={colors.categories[0]}
stroke={colors.categories[0]}
widthRatio={0.5}
fillOpacity={0.2}
strokeWidth={1}
horizontal
/>
<XAxis />
</ResponsiveXYChart>
);
}

export function ViolinPlotSeriesExample() {
const boxPlotData = statsData.map(s => s.boxPlot);
const violinData = statsData.map(s => ({ x: s.boxPlot.x, binData: s.binData }));
const values = boxPlotData.reduce((r, e) => r.push(e.min, e.max, ...e.outliers) && r, []);
const minYValue = Math.min(...values);
const maxYValue = Math.max(...values);
const yDomain = [minYValue - (0.1 * Math.abs(minYValue)),
maxYValue + (0.1 * Math.abs(minYValue))];
return (
<ResponsiveXYChart
theme={{}}
ariaLabel="Required label"
xScale={{
type: 'band',
paddingInner: 0.15,
paddingOuter: 0.3,
}}
yScale={{ type: 'linear',
domain: yDomain,
}}
renderTooltip={renderViolinPlotTooltip}
showYGrid
>
<PatternLines
id="hViolinLines"
height={3}
width={3}
stroke="#ced4da"
strokeWidth={1}
fill="rgba(0,0,0,0.3)"
orientation={['horizontal']}
/>
<YAxis numTicks={4} />
<ViolinPlotSeries
data={violinData}
fill="url(#hViolinLines)"
stroke="#22b8cf"
strokeWidth={0.5}
/>
<XAxis />
</ResponsiveXYChart>
);
}
4 changes: 3 additions & 1 deletion packages/demo/examples/01-xy-chart/data.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cityTemperature, appleStock, genRandomNormalPoints, letterFrequency } from '@vx/mock-data';
import { cityTemperature, appleStock, genRandomNormalPoints, letterFrequency, genStats } from '@vx/mock-data';
import { theme } from '@data-ui/xy-chart';

export const timeSeriesData = appleStock.filter((d, i) => i % 120 === 0).map(d => ({
Expand Down Expand Up @@ -123,3 +123,5 @@ export const circlePackData = Array(400).fill(null).map((_, i) => ({
fillOpacity: Math.max(0.4, Math.random()),
fill: theme.colors.categories[i % 2 === 0 ? 1 : 3],
}));

export const statsData = genStats(5);
36 changes: 36 additions & 0 deletions packages/demo/examples/01-xy-chart/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
LineSeries,
PointSeries,
StackedBarSeries,
BoxPlotSeries,
ViolinPlotSeries,

HorizontalReferenceLine,
PatternLines,
Expand All @@ -30,6 +32,12 @@ import RectPointComponent from './RectPointComponent';
import ResponsiveXYChart, { dateFormatter } from './ResponsiveXYChart';
import StackedAreaExample from './StackedAreaExample';
import ScatterWithHistogram from './ScatterWithHistograms';
import {
SimpleBoxPlotSeriesExample,
SingleBoxPlotSeriesExample,
HorizontalBoxPlotViolinPlotSeriesExample,
ViolinPlotSeriesExample,
} from './StatsSeriesExample';

import {
circlePackData,
Expand Down Expand Up @@ -488,6 +496,34 @@ export default {
</ResponsiveXYChart>
),
},
{
description: 'Box Plot Example',
components: [BoxPlotSeries],
example: () => (
<SimpleBoxPlotSeriesExample />
),
},
{
description: 'Single Horizontal Box Plot Example',
components: [BoxPlotSeries],
example: () => (
<SingleBoxPlotSeriesExample />
),
},
{
description: 'Horizontal BoxPlot With ViolinPlot Example',
components: [BoxPlotSeries, ViolinPlotSeries],
example: () => (
<HorizontalBoxPlotViolinPlotSeriesExample />
),
},
{
description: 'ViolinPlot Example',
components: [ViolinPlotSeries],
example: () => (
<ViolinPlotSeriesExample />
),
},
{
description: 'XAxis, YAxis -- orientation',
components: [XAxis, YAxis],
Expand Down
2 changes: 1 addition & 1 deletion packages/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"@storybook/addon-options": "^3.1.6",
"@storybook/react": "3.2.12",
"@vx/legend": "0.0.140",
"@vx/mock-data": "0.0.136",
"@vx/mock-data": "0.0.147",
"@vx/responsive": "0.0.140",
"@vx/scale": "0.0.140",
"aphrodite": "^1.2.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/xy-chart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ Series | supported x scale type | supported y scale types | data shape | voronoi
`<GroupedBarSeries/>` | band | linear | `{ x, y }` (colors controlled with groupFills & groupKeys) | no
`<CirclePackSeries/>` | time, linear | y is computed | `{ x [, size] }` | no
`<IntervalSeries/>` | time, linear | linear | `{ x0, x1 [, fill, stroke] }` | no
`<BoxPlotSeries/>` | linear, band | band, linear | `{ x (or y), min, max, median, firstQuartile, thirdQuartile, outliers [, fill, stroke] }` | no
`<ViolinPlotSeries/>` | linear, band | band, linear | `{ x (or y), binData [, fill, stroke] }` | no


\* The y boundaries of the `<AreaSeries/>` may be specified by either
- defined `y0` and `y1` values or
Expand Down
1 change: 1 addition & 0 deletions packages/xy-chart/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@vx/responsive": "0.0.140",
"@vx/scale": "0.0.140",
"@vx/shape": "0.0.145",
"@vx/stats": "0.0.147",
"@vx/tooltip": "0.0.140",
"@vx/voronoi": "0.0.140",
"d3-array": "^1.2.0",
Expand Down
3 changes: 3 additions & 0 deletions packages/xy-chart/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export { default as LineSeries } from './series/LineSeries';
export { default as PointSeries, pointComponentPropTypes } from './series/PointSeries';
export { default as StackedAreaSeries } from './series/StackedAreaSeries';
export { default as StackedBarSeries } from './series/StackedBarSeries';
export { default as BoxPlotSeries } from './series/BoxPlotSeries';
export { default as ViolinPlotSeries } from './series/ViolinPlotSeries';
export { computeStats } from '@vx/stats';

export { default as HorizontalReferenceLine } from './annotation/HorizontalReferenceLine';
export { default as CrossHair } from './chart/CrossHair';
Expand Down
Loading

0 comments on commit f5d4f42

Please sign in to comment.