Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dataset trans #13065

Merged
merged 11 commits into from
Jul 31, 2020
70 changes: 70 additions & 0 deletions extension-src/dataTool/boxplotTransform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { DataTransformOption, ExternalDataTransform } from '../../src/data/helper/transform';
import prepareBoxplotData from './prepareBoxplotData';
import { isArray, each } from 'zrender/src/core/util';
// import { throwError, makePrintable } from '../../src/util/log';


export interface BoxplotTransformOption extends DataTransformOption {
type: 'echarts-extension:boxplot';
config: {
boundIQR?: number | 'none',
layout?: 'horizontal' | 'vertical'
}
}

export const boxplotTransform: ExternalDataTransform<BoxplotTransformOption> = {

type: 'echarts-extension:boxplot',

// PEDING: enhance to filter by index rather than create new data
transform: function transform(params) {
const source = params.source;
const config = params.config || {};

const sourceData = source.data;
if (
!isArray(sourceData)
|| (sourceData[0] && !isArray(sourceData[0]))
) {
throw new Error(
'source data is not applicable for this boxplot transform. Expect number[][].'
);
}

const result = prepareBoxplotData(
source.data as number[][],
config
);

const boxData = result.boxData as (number | string)[][];
each(boxData, function (item, dataIdx) {
item.unshift(result.axisData[dataIdx]);
});

return [{
data: boxData
}, {
data: result.outliers
}];
}
};

3 changes: 3 additions & 0 deletions extension-src/dataTool/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
import * as echarts from 'echarts';
import * as gexf from './gexf';
import prepareBoxplotData from './prepareBoxplotData';
import { boxplotTransform } from './boxplotTransform';

export const version = '1.0.0';

export {gexf};

export {prepareBoxplotData};
export {boxplotTransform};

// For backward compatibility, where the namespace `dataTool` will
// be mounted on `echarts` is the extension `dataTool` is imported.
Expand All @@ -36,4 +38,5 @@ if (echarts.dataTool) {
echarts.dataTool.version = version;
echarts.dataTool.gexf = gexf;
echarts.dataTool.prepareBoxplotData = prepareBoxplotData;
echarts.dataTool.boxplotTransform = boxplotTransform;
}
19 changes: 14 additions & 5 deletions extension-src/dataTool/prepareBoxplotData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* under the License.
*/

// @ts-nocheck

function asc<T extends number[]>(arr: T): T {
arr.sort(function (a, b) {
Expand Down Expand Up @@ -59,11 +58,21 @@ function quantile(ascArr: number[], p: number): number {
* axisData: Array.<string>
* }
*/
export default function (rawData, opt) {
opt = opt || [];
export default function (
rawData: number[][],
opt: {
boundIQR?: number | 'none',
layout?: 'horizontal' | 'vertical'
}
): {
boxData: number[][]
outliers: number[][]
axisData: string[]
} {
opt = opt || {};
const boxData = [];
const outliers = [];
const axisData = [];
const axisData: string[] = [];
const boundIQR = opt.boundIQR;
const useExtreme = boundIQR === 'none' || boundIQR === 0;

Expand All @@ -77,7 +86,7 @@ export default function (rawData, opt) {
const min = ascList[0];
const max = ascList[ascList.length - 1];

const bound = (boundIQR == null ? 1.5 : boundIQR) * (Q3 - Q1);
const bound = (boundIQR == null ? 1.5 : boundIQR as number) * (Q3 - Q1);

const low = useExtreme
? min
Expand Down
2 changes: 1 addition & 1 deletion src/chart/bar/BarView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ function updateStyle(

// In case width or height are too small.
function getLineWidth(
itemModel: Model<BarSeriesOption>,
itemModel: Model<BarDataItemOption>,
rawLayout: RectLayout
) {
const lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
Expand Down
3 changes: 3 additions & 0 deletions src/chart/boxplot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import './boxplot/BoxplotSeries';
import './boxplot/BoxplotView';
import boxplotVisual from './boxplot/boxplotVisual';
import boxplotLayout from './boxplot/boxplotLayout';
import { boxplotTransform } from './boxplot/boxplotTransform';

echarts.registerVisual(boxplotVisual);
echarts.registerLayout(boxplotLayout);
echarts.registerTransform(boxplotTransform);

69 changes: 69 additions & 0 deletions src/chart/boxplot/boxplotTransform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { DataTransformOption, ExternalDataTransform } from '../../data/helper/transform';
import prepareBoxplotData from './prepareBoxplotData';
import { isArray } from 'zrender/src/core/util';
import { throwError, makePrintable } from '../../util/log';


export interface BoxplotTransformOption extends DataTransformOption {
type: 'boxplot';
config: {
boundIQR?: number | 'none',
layout?: 'horizontal' | 'vertical'
}
}

export const boxplotTransform: ExternalDataTransform<BoxplotTransformOption> = {

type: 'echarts:boxplot',

transform: function transform(params) {
const source = params.source;
const config = params.config || {};

const sourceData = source.data;
if (
!isArray(sourceData)
|| (sourceData[0] && !isArray(sourceData[0]))
) {
let errMsg = '';
if (__DEV__) {
errMsg = makePrintable(
'source data is not applicable for this boxplot transform. Expect number[][].',
'But actually', sourceData
);
}
throwError(errMsg);
}

const result = prepareBoxplotData(
source.data as number[][],
config
);

return [{
data: result.boxData
}, {
data: result.outliers
}];
}
};

91 changes: 91 additions & 0 deletions src/chart/boxplot/prepareBoxplotData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { quantile, asc } from '../../util/number';


/**
* See:
* <https://en.wikipedia.org/wiki/Box_plot#cite_note-frigge_hoaglin_iglewicz-2>
* <http://stat.ethz.ch/R-manual/R-devel/library/grDevices/html/boxplot.stats.html>
*
* Helper method for preparing data.
*
* @param rawData like
* [
* [12,232,443], (raw data set for the first box)
* [3843,5545,1232], (raw datat set for the second box)
* ...
* ]
* @param opt.boundIQR=1.5 Data less than min bound is outlier.
* default 1.5, means Q1 - 1.5 * (Q3 - Q1).
* If 'none'/0 passed, min bound will not be used.
* @param opt.layout='horizontal'
* Box plot layout, can be 'horizontal' or 'vertical'
*/
export default function (
rawData: number[][],
opt: {
boundIQR?: number | 'none',
layout?: 'horizontal' | 'vertical'
}
): {
boxData: number[][]
outliers: number[][]
} {
opt = opt || {};
const boxData = [];
const outliers = [];
const boundIQR = opt.boundIQR;
const useExtreme = boundIQR === 'none' || boundIQR === 0;

for (let i = 0; i < rawData.length; i++) {
const ascList = asc(rawData[i].slice());

const Q1 = quantile(ascList, 0.25);
const Q2 = quantile(ascList, 0.5);
const Q3 = quantile(ascList, 0.75);
const min = ascList[0];
const max = ascList[ascList.length - 1];

const bound = (boundIQR == null ? 1.5 : boundIQR as number) * (Q3 - Q1);

const low = useExtreme
? min
: Math.max(min, Q1 - bound);
const high = useExtreme
? max
: Math.min(max, Q3 + bound);

boxData.push([i, low, Q1, Q2, Q3, high]);

for (let j = 0; j < ascList.length; j++) {
const dataItem = ascList[j];
if (dataItem < low || dataItem > high) {
const outlier = [i, dataItem];
opt.layout === 'vertical' && outlier.reverse();
outliers.push(outlier);
}
}
}
return {
boxData: boxData,
outliers: outliers
};
}
5 changes: 3 additions & 2 deletions src/chart/custom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ import {
DisplayState,
ECElement,
DisplayStateNonNormal,
BlurScope
BlurScope,
SeriesDataType
} from '../util/types';
import Element, { ElementProps, ElementTextConfig } from 'zrender/src/Element';
import prepareCartesian2d from '../coord/cartesian/prepareCustom';
Expand Down Expand Up @@ -410,7 +411,7 @@ class CustomSeriesModel extends SeriesModel<CustomSeriesOption> {
return createListFromArray(this.getSource(), this);
}

getDataParams(dataIndex: number, dataType?: string, el?: Element): CallbackDataParams & {
getDataParams(dataIndex: number, dataType?: SeriesDataType, el?: Element): CallbackDataParams & {
info: CustomExtraElementInfo
} {
const params = super.getDataParams(dataIndex, dataType) as ReturnType<CustomSeriesModel['getDataParams']>;
Expand Down
2 changes: 1 addition & 1 deletion src/chart/funnel/FunnelSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class FunnelSeriesModel extends SeriesModel<FunnelSeriesOption> {
this._defaultLabelLine(option);
}

getInitialData(option: FunnelSeriesOption, ecModel: GlobalModel): List {
getInitialData(this: FunnelSeriesModel, option: FunnelSeriesOption, ecModel: GlobalModel): List {
return createListSimply(this, {
coordDimensions: ['value'],
encodeDefaulter: zrUtil.curry(makeSeriesEncodeForNameBased, this)
Expand Down
18 changes: 7 additions & 11 deletions src/chart/graph/GraphSeries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ import {
Dictionary,
LineLabelOption,
StatesOptionMixin,
GraphEdgeItemObject,
OptionDataValueNumeric,
TooltipRenderMode
} from '../../util/types';
import SeriesModel from '../../model/Series';
Expand Down Expand Up @@ -108,16 +110,10 @@ export interface GraphEdgeStateOption {
lineStyle?: GraphEdgeLineStyleOption
label?: LineLabelOption
}
export interface GraphEdgeItemOption
extends GraphEdgeStateOption, StatesOptionMixin<GraphEdgeStateOption, ExtraEdgeStateOption> {
/**
* Name or index of source node.
*/
source?: string | number
/**
* Name or index of target node.
*/
target?: string | number
export interface GraphEdgeItemOption extends
GraphEdgeStateOption,
StatesOptionMixin<GraphEdgeStateOption, ExtraEdgeStateOption>,
GraphEdgeItemObject<OptionDataValueNumeric> {

value?: number

Expand Down Expand Up @@ -273,7 +269,7 @@ class GraphSeriesModel extends SeriesModel<GraphSeriesOption> {
defaultEmphasis(option, 'edgeLabel', ['show']);
}

getInitialData(option: GraphSeriesOption, ecModel: GlobalModel) {
getInitialData(option: GraphSeriesOption, ecModel: GlobalModel): List {
const edges = option.edges || option.links || [];
const nodes = option.data || option.nodes || [];
const self = this;
Expand Down
Loading