@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
71 lines (65 loc) • 2.79 kB
JavaScript
;
function jaccardSimilarity(columnA, columnB) {
if (columnA.length !== columnB.length) throw new Error("Columns must be of the same length");
let intersection = 0, union = 0;
for (let i = 0; i < columnA.length; i++) 1 !== columnA[i] && 1 !== columnB[i] || (union++,
1 === columnA[i] && 1 === columnB[i] && intersection++);
return intersection / union;
}
function calculateClusterDistance(clusterA, clusterB) {
let sumDistance = 0;
for (const itemA of clusterA.children) for (const itemB of clusterB.children) {
sumDistance += 1 - jaccardSimilarity(itemA.value, itemB.value);
}
return sumDistance / (clusterA.children.length * clusterB.children.length);
}
function calculateDistanceMatrix(data) {
const n = data.length, distanceMatrix = Array.from({
length: n
}, (() => Array(n).fill(0)));
let minDistance = 1;
const distancePair = [ 0, 0 ];
for (let i = 0; i < n; i++) for (let j = i + 1; j < n; j++) {
const distance = calculateClusterDistance(data[i], data[j]);
distanceMatrix[i][j] = distance, distanceMatrix[j][i] = distance, distance < minDistance && (minDistance = distance,
distancePair[0] = i, distancePair[1] = j);
}
return {
distanceMatrix: distanceMatrix,
minDistance: minDistance,
distancePair: distancePair
};
}
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.agglomerativeHierarchicalClustering = exports.calculateDistanceMatrix = exports.jaccardSimilarity = void 0,
exports.jaccardSimilarity = jaccardSimilarity, exports.calculateDistanceMatrix = calculateDistanceMatrix;
const agglomerativeHierarchicalClustering = (data, threshold = .4) => {
const clusters = data.map(((v, i) => ({
id: i,
children: [ v ]
}))), clusterMap = new Map;
let hasMerged = !0;
for (;hasMerged && clusters.length > 1; ) {
hasMerged = !1;
const {minDistance: minDistance, distancePair: distancePair} = calculateDistanceMatrix(clusters);
if (minDistance <= threshold) {
const mergedCluster = {
id: clusters.length,
children: [ ...clusters[distancePair[0]].children, ...clusters[distancePair[1]].children ]
};
clusters.splice(distancePair[0], 1), clusters.splice(distancePair[1] - 1, 1), clusters.push(mergedCluster),
hasMerged = !0;
}
}
return clusters.forEach(((v, i) => {
v.children.forEach((item => {
clusterMap.set(item.id, i);
}));
})), {
clusters: clusters,
clusterMap: clusterMap
};
};
exports.agglomerativeHierarchicalClustering = agglomerativeHierarchicalClustering;
//# sourceMappingURL=cluster.js.map