@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
60 lines (51 loc) • 3.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.StatisticsAlo = exports.getAbnormalByIQR = exports.getAbnormalByZScores = void 0;
const vutils_1 = require("@visactor/vutils"), type_1 = require("../../type"), types_1 = require("../../../../types"), common_1 = require("../../../../utils/common"), statistics_1 = require("../statistics"), utils_1 = require("../../utils");
function getAbnormalByZScores(data, threshold = 3) {
const {mean: mean, stdDev: stdDev} = (0, statistics_1.getMeanAndstdDev)(data.map((v => v.value)));
return data.filter((v => Math.abs((v.value - mean) / stdDev) >= threshold)).map((v => v.index));
}
function calculateQuantile(sortedData, quantile) {
const pos = (sortedData.length - 1) * quantile, base = Math.floor(pos), rest = pos - base;
return void 0 !== sortedData[base + 1] ? sortedData[base] + rest * (sortedData[base + 1] - sortedData[base]) : sortedData[base];
}
function getAbnormalByIQR(data) {
const sortedData = data.slice().sort(((a, b) => a.value - b.value)), dataList = sortedData.map((v => v.value)), q1 = calculateQuantile(dataList, .25), q3 = calculateQuantile(dataList, .75), iqr = q3 - q1, lowerBound = q1 - 1.5 * iqr, upperBound = q3 + 1.5 * iqr;
return sortedData.filter((dataPoint => dataPoint.value < lowerBound || dataPoint.value > upperBound)).map((v => v.index));
}
exports.getAbnormalByZScores = getAbnormalByZScores, exports.getAbnormalByIQR = getAbnormalByIQR;
const zscoreIQRAlgoFunc = (context, options) => {
const result = [], {threshold: threshold = 3} = options || {}, {seriesDataMap: seriesDataMap, cell: cell, spec: spec} = context, {y: celly} = cell, yField = (0,
vutils_1.isArray)(celly) ? celly.flat() : [ celly ];
return Object.keys(seriesDataMap).forEach((group => {
const dataset = seriesDataMap[group];
yField.forEach((field => {
if ((0, utils_1.isPercenSeries)(spec, field)) return;
const dataList = dataset.map(((d, index) => ({
index: index,
value: Number(d.dataItem[field])
}))).filter((v => (0, common_1.isValidData)(v.value) && !isNaN(v.value))), zScoreResult = dataList.length >= 30 ? getAbnormalByZScores(dataList, threshold) : null, iqrResult = dataList.length >= 10 ? getAbnormalByIQR(dataList) : null;
((zScoreResult ? (0, common_1.getIntersection)(zScoreResult, iqrResult) : iqrResult) || []).forEach((index => {
const insightDataItem = dataset[index], lofInsight = {
type: type_1.InsightType.Outlier,
data: [ insightDataItem ],
fieldId: field,
value: insightDataItem.dataItem[field],
significant: 1,
seriesName: group
};
result.push(lofInsight);
}));
}));
})), result;
};
exports.StatisticsAlo = {
name: "statistics",
forceChartType: [ types_1.ChartType.DualAxisChart, types_1.ChartType.LineChart, types_1.ChartType.BarChart, types_1.ChartType.AreaChart, types_1.ChartType.RadarChart, types_1.ChartType.PieChart, types_1.ChartType.RoseChart, types_1.ChartType.WaterFallChart ],
insightType: type_1.InsightType.Outlier,
algorithmFunction: zscoreIQRAlgoFunc,
supportPercent: !1
};
//# sourceMappingURL=statistics.js.map