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

74 lines (67 loc) 4.26 kB
"use strict"; var __importDefault = this && this.__importDefault || function(mod) { return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.LOFOutlier = exports.LOF = void 0; const euclidean_distance_1 = __importDefault(require("euclidean-distance")), vutils_1 = require("@visactor/vutils"), type_1 = require("../../type"), types_1 = require("../../../../types"), utils_1 = require("../../utils"), knn = (k, pIndex, distanceMap) => { const distanceArr = distanceMap[pIndex]; return distanceMap.map(((data, index) => [ index, distanceArr[index] ])).filter((([index, distance]) => index !== pIndex)).sort((([index1, distance1], [index2, distance2]) => distance1 - distance2)).slice(0, k); }, kd = (knnMap, pIndex) => { const kNeighbors = knnMap[pIndex], [index, distance] = kNeighbors.reduce(((acc, dis) => acc[1] > dis[1] ? acc : dis)); return distance; }, rd = (knnMap, distanceMap, pIndex, oIndex) => Math.max(kd(knnMap, oIndex), distanceMap[pIndex][oIndex]), sigmaRdCalc = (nearestArray, knnMap, distanceMap, pIndex) => nearestArray.map((([oIndex, distance]) => rd(knnMap, distanceMap, pIndex, oIndex))).reduce(((d1, d2) => d1 + d2)), lrd = (pIndex, knnMap, distanceMap) => { const nearestArray = knnMap[pIndex], sigmaRd = sigmaRdCalc(nearestArray, knnMap, distanceMap, pIndex); return sigmaRd - 0 <= Number.EPSILON ? 1 : nearestArray.length / sigmaRd; }, onePointLOF = (dataIndex, knnMap, lrdArray) => { const nearestArray = knnMap[dataIndex]; return nearestArray.map((([oIndex]) => lrdArray[oIndex] / lrdArray[dataIndex])).reduce(((d1, d2) => d1 + d2)) / nearestArray.length; }, autoK = dataLength => dataLength > 10 ? 8 : dataLength > 4 ? 4 : 2, LOF = (dataList, threshold = 3, propsK) => { const k = propsK || ((dataLength = dataList.length) > 10 ? 8 : dataLength > 4 ? 4 : 2); var dataLength; if (k >= dataList.length) return []; const distanceMap = new Array(dataList.length).fill(0).map((d => [])); for (let i = 0; i < dataList.length; i++) for (let j = i + 1; j < dataList.length; j++) { const distance = (0, euclidean_distance_1.default)([ dataList[i] ], [ dataList[j] ]); distanceMap[i][j] = distance, distanceMap[j][i] = distance; } const knnMap = dataList.map(((v, index) => knn(k, index, distanceMap))), lrdArr = dataList.map(((v, index) => lrd(index, knnMap, distanceMap))); return dataList.map(((v, index) => onePointLOF(index, knnMap, lrdArr))).map(((score, index) => score >= threshold ? { index: index, score: score } : void 0)).filter(Boolean); }; exports.LOF = LOF; const lofAlgoFunc = (context, options) => { const result = [], {k: k, 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 => Number(d.dataItem[field]))); (0, exports.LOF)(dataList, threshold, k).forEach((insight => { const {score: score, index: index} = insight, insightDataItem = dataset[index], lofInsight = { type: type_1.InsightType.Outlier, data: [ insightDataItem ], fieldId: field, value: insightDataItem.dataItem[field], significant: score / threshold, seriesName: group }; result.push(lofInsight); })); })); })), result; }; exports.LOFOutlier = { name: "lof", 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: lofAlgoFunc, supportPercent: !1 }; //# sourceMappingURL=lof.js.map