UNPKG

@visactor/vmind

Version:

<div align="center"> <a href="https://github.com/VisActor#gh-light-mode-only" target="_blank"> <img alt="VisActor Logo" width="200" src="https://github.com/VisActor/.github/blob/main/profile/logo_500_200_light.svg"/> </a> <a href="https://githu

68 lines (58 loc) 3.09 kB
import { isArray } from "@visactor/vutils"; import { InsightType } from "../../type"; import { ChartType, DataType } from "../../../../types"; import { getIntersection } from "../../../../utils/common"; import { getAbnormalByIQR, getAbnormalByZScores } from "./statistics"; import { LOF } from "./lof"; import { isPercenSeries } from "../../utils"; function getDistanceList(dataList, isTimeSeries) { const res = [], n = dataList.length; let index = 0; if (isTimeSeries) for (let i = 0; i < n - 1; i++) res.push({ index: index++, indexPair: [ i, i + 1 ], value: Math.abs(dataList[i].value - dataList[i + 1].value) }); else for (let i = 0; i < n - 1; i++) for (let j = i + 1; j < n; j++) { const distance = Math.abs(dataList[i].value - dataList[j].value); res.push({ index: index++, indexPair: [ i, j ], value: distance }); } return res; } const difference = (context, options) => { const result = [], {zScore: zScore = 3, lofThreshold: lofThreshold = 3} = options || {}, {seriesDataMap: seriesDataMap, cell: cell, fieldInfo: fieldInfo, spec: spec} = context, {y: celly, x: cellx} = cell, yField = isArray(celly) ? celly.flat() : [ celly ], xField = isArray(cellx) ? cellx[0] : cellx, isTimeSeries = [ DataType.TIME, DataType.DATE ].includes(fieldInfo.find((info => info.fieldName === xField)).type); return Object.keys(seriesDataMap).forEach((group => { const dataset = seriesDataMap[group]; yField.forEach((field => { const dataList = dataset.map(((d, index) => ({ index: index, value: d.dataItem[field] }))); if (isPercenSeries(spec, field)) return; const distanceList = getDistanceList(dataList, isTimeSeries), zScoreResult = distanceList.length >= 30 ? getAbnormalByZScores(distanceList, zScore) : null, iqrResult = distanceList.length >= 10 ? getAbnormalByIQR(distanceList) : [], staticResult = zScoreResult ? getIntersection(zScoreResult, iqrResult) : iqrResult, lofResult = LOF(distanceList.map((v => v.value)), lofThreshold).map((v => v.index)); (getIntersection(staticResult, lofResult) || []).forEach((index => { const distanceItem = distanceList[index], lofInsight = { type: InsightType.PairOutlier, data: distanceItem.indexPair.map((v => dataset[dataList[v].index])), fieldId: field, value: distanceItem.value, significant: 1, seriesName: group }; result.push(lofInsight); })); })); })), result; }; export const DifferenceAlg = { name: "difference", forceChartType: [ ChartType.DualAxisChart, ChartType.LineChart, ChartType.BarChart, ChartType.AreaChart, ChartType.WaterFallChart ], insightType: InsightType.PairOutlier, algorithmFunction: difference, supportPercent: !1, supportStack: !1 }; //# sourceMappingURL=difference.js.map