@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
54 lines (47 loc) • 2.67 kB
JavaScript
import { isArray } from "@visactor/vutils";
import clustering from "density-clustering";
import normalize from "array-normalize";
import { InsightType } from "../../type";
import { ChartType, ROLE } from "../../../../types";
const isMeasureField = (field, fieldInfo) => {
const fieldInfoItem = fieldInfo.find((v => v.fieldName === field));
return fieldInfoItem && fieldInfoItem.role === ROLE.MEASURE;
}, dbscanAlgo = (context, options) => {
const {seriesDataMap: seriesDataMap, cell: cell, fieldInfo: fieldInfo} = context, {eps: eps = .2, minPts: minPts = 5} = options || {}, {y: celly, x: cellx, color: color, size: size} = cell, yField = isArray(celly) ? celly.flat() : [ celly ], xField = isArray(cellx) ? cellx[0] : cellx, allMeasureFields = [ isArray(color) ? color[0] : color, isArray(size) ? size[0] : size ].filter((v => !!v && isMeasureField(v, fieldInfo))), result = [];
return Object.keys(seriesDataMap).forEach((series => {
const seriesDataset = seriesDataMap[series];
if (seriesDataset.length <= minPts || seriesDataset.length < 5) return;
const flatDataset = seriesDataset.reduce(((prev, cur) => {
var _a, _b;
return [ ...prev, null !== (_a = cur.dataItem[xField]) && void 0 !== _a ? _a : 0, null !== (_b = cur.dataItem[yField[0]]) && void 0 !== _b ? _b : 0, ...allMeasureFields.map((v => {
var _a;
return null !== (_a = cur.dataItem[v]) && void 0 !== _a ? _a : 0;
})) ];
}), []), dimensionCount = 2 + allMeasureFields.length, normalizedDataset = normalize(flatDataset, dimensionCount), clusterDataset = [];
for (let index = 0; index < normalizedDataset.length; index += dimensionCount) {
const item = normalizedDataset.slice(index, index + dimensionCount);
clusterDataset.push(item);
}
const dbscan = new clustering.DBSCAN, insights = (dbscan.run(clusterDataset, eps, minPts),
dbscan.noise.map((noiseIndex => {
const d = seriesDataset[noiseIndex];
return {
type: InsightType.Outlier,
data: [ d ],
fieldId: [ xField, yField[0] ],
value: [ d.dataItem[xField], d.dataItem[yField[0]] ],
significant: 1,
seriesName: series
};
})));
result.push(...insights);
})), result;
};
export const DBSCANOutlier = {
name: "dbscan",
chartType: [ ChartType.ScatterPlot ],
forceChartType: [ ChartType.ScatterPlot ],
insightType: InsightType.Outlier,
algorithmFunction: dbscanAlgo
};
//# sourceMappingURL=dbscan.js.map