Skip to content

Commit

Permalink
Split pipeline data (#44)
Browse files Browse the repository at this point in the history
* feat(CA): split pipeline

* feat(CA): split pipeline

* v0.1.3-alpha.25

* docs: how it works

* v0.1.3-alpha.26

* refactor(demo): add different test sections

* feat(demo): pipeline test

* feat(chart-advisor): add type to libConfig

* feat(chart-advisor): specToLibConfig add chart type
  • Loading branch information
neoddish committed Apr 22, 2020
1 parent 4bfeee3 commit 443fa9b
Show file tree
Hide file tree
Showing 17 changed files with 653 additions and 331 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Expand Up @@ -3,6 +3,7 @@
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"prettier"
],
"parser": "@typescript-eslint/parser",
Expand Down
74 changes: 74 additions & 0 deletions HOWITWORKS.md
@@ -0,0 +1,74 @@
# How it Works

the graph is ugly but the pipeline could be something like this:

![AVA Pipeline](https://gw.alipayobjects.com/zos/antfincdn/YBzJnTR4My/avapipeline.png)

## Data to Data Property Schema

We analyze the _properties_ and _features_ of the given dataset and record them as a schema.

```js
// This is the sample dataset:
const data = [
{f1: "a", f2: 100},
{f1: "b", f2: 300},
{f1: "c", f2: 340},
{f1: "d", f2: 630}
];

// This is the property schema of the sample dataset:
const dataPropSchema = [
{
"count": 4,
"distinct": 4,
"type": "string",
"recommendation": "string",
"missing": 0,
"samples": [ "a", "b", "c", "d" ],
"valueMap": { "a": 1, "b": 1, "c": 1, "d": 1 },
"maxLength": 1,
"minLength": 1,
"meanLength": 1,
"containsChars": true,
"containsDigits": false,
"containsSpace": false,
"containsNonWorlds": false,
"name": "f1",
"levelOfMeasurements": [ "Nominal" ]
},
{
"count": 4,
"distinct": 4,
"type": "integer",
"recommendation": "integer",
"missing": 0,
"samples": [ 100, 300, 340, 630 ],
"valueMap": { "100": 1, "300": 1, "340": 1, "630": 1 },
"minimum": 100,
"maximum": 630,
"mean": 342.5,
"percentile5": 100,
"percentile25": 100,
"percentile50": 300,
"percentile75": 340,
"percentile95": 630,
"sum": 1370,
"variance": 35818.75,
"stdev": 189.2584212129014,
"zeros": 0,
"name": "f2",
"levelOfMeasurements": [ "Interval", "Discrete" ]
}
]
```

To get the data props schema, we can use _@antv/dw-analyzer_ of DataWizard.

```js
import * as DWAnalyzer from '@antv/dw-analyzer';

const dataPropSchema = DWAnalyzer.typeAll(dataset);
```

and then add levelOfMeasurements to it.
63 changes: 63 additions & 0 deletions common/reviews/api/chart-advisor.api.md
Expand Up @@ -4,6 +4,27 @@
```ts

import * as DWAnalyzer from '@antv/dw-analyzer';
import { LevelOfMeasurement } from '@antv/knowledge';

// @beta (undocumented)
export interface Advice {
// (undocumented)
channels: Channels;
// (undocumented)
score: number;
// (undocumented)
type: string;
}

// @public (undocumented)
export interface AdvisorOptions {
description?: string;
preferences?: Preferences;
purpose?: string;
title?: string;
}

// @public
export function autoChart(container: HTMLElement, data: any[] | Promise<any[]>, options?: AutoChartOptions): Promise<void>;

Expand All @@ -25,11 +46,53 @@ export interface AutoChartOptions {
toolbar?: boolean;
}

// @beta (undocumented)
export interface Channels {
// (undocumented)
angle?: string;
// (undocumented)
color?: string;
// (undocumented)
radius?: string;
// (undocumented)
series?: string;
// (undocumented)
size?: string;
// (undocumented)
x?: string;
// (undocumented)
x2?: string;
// (undocumented)
y?: string;
// (undocumented)
y2?: string;
}

// @beta (undocumented)
export type ChartLibrary = 'G2Plot' | 'antdCharts';

// @beta
export function dataPropsToSpecs(dataProps: FieldInfo[], options?: AdvisorOptions): Advice[];

// @beta
export function dataToDataProps(data: any[]): FieldInfo[];

// @beta (undocumented)
export interface FieldInfo extends DWAnalyzer.FieldInfo {
// (undocumented)
levelOfMeasurements: LevelOfMeasurement[];
// (undocumented)
name: string;
}

// @public
export interface Preferences {
// (undocumented)
canvasLayout: 'landscape' | 'portrait';
}

// @beta
export function specToLibConfig(advice: Advice, libraryName: ChartLibrary): any;


```
83 changes: 83 additions & 0 deletions demo/AutoChartTest.tsx
@@ -0,0 +1,83 @@
import * as React from 'react';
import AutoChart from './auto-chart';
// import { DataSamples } from './data-samples';

export function AutoChartTest() {
return (
<>
<AutoChart
data={[
{ f1: '2019-01', f2: 100 },
{ f1: '2019-02', f2: 300 },
{ f1: '2019-03', f2: 340 },
{ f1: '2019-04', f2: 630 },
]}
title="expect: Line"
/>

{/* <AutoChart
data={[
{ f1: 'a', f2: 100 },
{ f1: 'b', f2: 300 },
{ f1: 'c', f2: 430 },
{ f1: 'd', f2: 630 },
]}
title="expect: Column"
/> */}

{/* <AutoChart
data={[
{ f1: 'a', f2: 70 },
{ f1: 'b', f2: 120 },
{ f1: 'c', f2: 900 },
{ f1: 'd', f2: 630 },
]}
title="expect: Pie"
/> */}

{/* <AutoChart data={[]} title="ζ΅‹θ―•" description="ζ΅‹θ―•" /> */}

{/* <AutoChart
data={DataSamples.ForChartType('percent_stacked_bar_chart')}
purpose="Proportion"
title="expect: Percentage Stacked Bar"
/> */}

{/* <AutoChart data={DataSamples.ForChartType('line_chart')} title="expect: Line" />
<AutoChart data={DataSamples.ForChartType('area_chart')} title="expect: Area" /> */}

{/* <AutoChart data={DataSamples.ForChartType('area_chart')} title="expect: Area" config={{ type: 'StepLine' }} /> */}

{/* <AutoChart
data={[
{ f1: '2019-01', f2: 100 },
{ f1: '2019-02', f2: 300 },
{ f1: '2019-03', f2: 340 },
{ f1: '2019-04', f2: 630 },
]}
title="try: Stacked Area"
description="ι€‚εˆεš stacked area"
config={{ configs: { xField: 'f1', yField: 'f2' }, type: 'StepLine' }}
/> */}

{/* <AutoChart data={DataSamples.ForChartType('pie_chart')} title="expect: Pie" />
<AutoChart data={DataSamples.ForChartType('scatter_plot')} title="expect: Scatter" />
<AutoChart data={DataSamples.ForChartType('bubble_chart')} title="expect: Bubble" /> */}

{/* <AutoChart data={DataSamples.ForChartType('histogram')} title="expect: Histogram" /> */}
{/* <AutoChart
data={[
{ f1: 'a', f2: 100 },
{ f1: 'b', f2: 200 },
{ f1: 'c', f2: 300 },
{ f1: 'd', f2: 400 },
{ f1: 'e', f2: 630 },
]}
title="expect: Rose"
config={{ configs: { colorField: 'f1', categoryField: 'f1', radiusField: 'f2' }, type: 'Rose' }}
/> */}
{/* <AutoChart data={DataSamples.ForChartType('heatmap')} title="expect: Heatmap" />
<AutoChart data={DataSamples.ForChartType('grouped_column_chart')} title="expect: Area" /> */}
</>
);
}
5 changes: 5 additions & 0 deletions demo/FindInsightTest.tsx
@@ -0,0 +1,5 @@
import * as React from 'react';

export function FindInsightTest() {
return <div>findInsight</div>;
}
135 changes: 135 additions & 0 deletions demo/PipelineTest.tsx
@@ -0,0 +1,135 @@
import React, { useRef, useEffect } from 'react';
import * as G2Plot from '@antv/g2plot';
import { DataSamples } from './data-samples';
import { dataToDataProps, dataPropsToSpecs, specToLibConfig } from '../packages/chart-advisor/src/index';

function prettyJSON(json: any) {
return JSON.stringify(
json,
function(_, v) {
for (const p in v) {
if (v[p] instanceof Object) {
return v;
}
}
return JSON.stringify(v, null, 1);
},
2
)
.replace(/\\n/g, '')
.replace(/\\/g, '')
.replace(/"\[/g, '[')
.replace(/\]"/g, ']')
.replace(/"\{/g, '{')
.replace(/\}"/g, ' }');
}

function JSONToTable(jsonArray: any) {
if (!Array.isArray(jsonArray)) {
return <div>Data is NOT array!</div>;
}

if (jsonArray.length === 0) {
return <div>Data array is empty!</div>;
}

const fields = Object.keys(jsonArray[0]);

return (
<table className="columnTable">
<thead>
<tr>
{fields.map((fieldTitle) => {
return <th key={fieldTitle}>{fieldTitle}</th>;
})}
</tr>
</thead>
<tbody>
{jsonArray.map((row, index) => (
<tr key={index}>
{fields.map((field) => (
<td key={field}>{`${row[field]}`}</td>
))}
</tr>
))}
</tbody>
</table>
);
}

export function PipelineTest() {
const datasample = DataSamples.ForChartType('percent_stacked_bar_chart');

const dataProps = dataToDataProps(datasample);
const specs = dataPropsToSpecs(dataProps);
const libConfigs = specs.map((spec) => specToLibConfig(spec, 'G2Plot')).filter((e) => e.type && e.configs);

const { type, configs } = libConfigs[0];
// @ts-ignore
const ChartConstructor = G2Plot[type];
const chartdom = useRef(null);
useEffect(() => {
const chart = new ChartConstructor(chartdom.current, {
data: datasample,
...configs,
});
chart.render();
});

const dataInJSON = (
<div style={{ display: 'flex', flexDirection: 'column', width: '45%' }}>
<h3>Data in JSON</h3>
<textarea style={{ height: '100%', overflowY: 'scroll' }} defaultValue={prettyJSON(datasample)} />
</div>
);

const dataInTable = (
<div style={{ display: 'flex', flexDirection: 'column', width: '45%' }}>
<h3>Data in Table</h3>
<div style={{ height: '100%', overflowY: 'scroll' }}>{JSONToTable(datasample)}</div>
</div>
);

return (
<>
{/* data */}
<div style={{ display: 'flex', justifyContent: 'space-evenly', minHeight: '200px', maxHeight: '300px' }}>
{dataInJSON}
{dataInTable}
</div>
{/* data props */}
<div>
<h3>data props</h3>

{[dataProps].map((dataProps) => {
console.log('🍎 dataProps');
console.log(dataProps);
return `check console for '🍎 dataProps'`;
})}
</div>
{/* specs */}
<div>
<h3>specs</h3>
{[specs].map((specs) => {
console.log('πŸ’¬ specs');
console.log(specs);
return `check console for 'πŸ’¬ specs'`;
})}
</div>
{/* lib config */}
<div>
<h3>lib config (G2Plot)</h3>
{[libConfigs].map((libConfigs) => {
console.log('πŸ“ libConfigs');
console.log(libConfigs);
return `check console for 'πŸ“ libConfigs'`;
})}
</div>
{/* chart */}
<div>
<h3>chart top1</h3>
<div ref={chartdom}></div>
</div>
</>
);
}

0 comments on commit 443fa9b

Please sign in to comment.