@thi.ng/k-means
Advanced tools
Comparing version 0.2.0 to 0.2.1
@@ -6,2 +6,10 @@ # Change Log | ||
## [0.2.1](https://github.com/thi-ng/umbrella/compare/@thi.ng/k-means@0.2.0...@thi.ng/k-means@0.2.1) (2021-04-24) | ||
**Note:** Version bump only for package @thi.ng/k-means | ||
# [0.2.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/k-means@0.1.0...@thi.ng/k-means@0.2.0) (2021-04-20) | ||
@@ -8,0 +16,0 @@ |
@@ -48,8 +48,20 @@ import { IDistance } from "@thi.ng/distance"; | ||
/** | ||
* Means centroid strategy for WGS84 lat/lon positions. Unlike the default | ||
* {@link means} strategy, this one treats latitude values correctly in terms of | ||
* the ±180 deg boundary and ensures samples on either side of the Pacific are | ||
* forming correct centroids. | ||
* Means centroid strategy for decimal degree lat/lon positions (e.g. WGS84). | ||
* Unlike the default {@link means} strategy, this one treats latitude values | ||
* correctly in terms of the ±180 deg boundary and ensures samples on either | ||
* side of the Pacific are forming correct centroids. | ||
* | ||
* @remarks | ||
* When using this strategy, you should also use the | ||
* {@link @thi.ng/distance#HAVERSINE_LATLON} distance metric for | ||
* {@link KMeansOpts.distance}. | ||
* | ||
* @example | ||
* ```ts | ||
* kmeans(3, [...], { strategy: meansLatLon, dist: HAVERSINE_LATLON }) | ||
* ``` | ||
* | ||
* https://en.wikipedia.org/wiki/World_Geodetic_System | ||
*/ | ||
export declare const meansWgs84: CentroidStrategy; | ||
export declare const meansLatLon: CentroidStrategy; | ||
//# sourceMappingURL=kmeans.d.ts.map |
@@ -133,8 +133,20 @@ import { assert } from "@thi.ng/api"; | ||
/** | ||
* Means centroid strategy for WGS84 lat/lon positions. Unlike the default | ||
* {@link means} strategy, this one treats latitude values correctly in terms of | ||
* the ±180 deg boundary and ensures samples on either side of the Pacific are | ||
* forming correct centroids. | ||
* Means centroid strategy for decimal degree lat/lon positions (e.g. WGS84). | ||
* Unlike the default {@link means} strategy, this one treats latitude values | ||
* correctly in terms of the ±180 deg boundary and ensures samples on either | ||
* side of the Pacific are forming correct centroids. | ||
* | ||
* @remarks | ||
* When using this strategy, you should also use the | ||
* {@link @thi.ng/distance#HAVERSINE_LATLON} distance metric for | ||
* {@link KMeansOpts.distance}. | ||
* | ||
* @example | ||
* ```ts | ||
* kmeans(3, [...], { strategy: meansLatLon, dist: HAVERSINE_LATLON }) | ||
* ``` | ||
* | ||
* https://en.wikipedia.org/wiki/World_Geodetic_System | ||
*/ | ||
export const meansWgs84 = () => { | ||
export const meansLatLon = () => { | ||
let lat = 0; | ||
@@ -141,0 +153,0 @@ let lon = 0; |
@@ -98,3 +98,3 @@ 'use strict'; | ||
}; | ||
const meansWgs84 = () => { | ||
const meansLatLon = () => { | ||
let lat = 0; | ||
@@ -124,3 +124,3 @@ let lon = 0; | ||
exports.means = means; | ||
exports.meansWgs84 = meansWgs84; | ||
exports.meansLatLon = meansLatLon; | ||
exports.medians = medians; |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@thi.ng/api"),require("@thi.ng/distance"),require("@thi.ng/random"),require("@thi.ng/vectors")):"function"==typeof define&&define.amd?define(["exports","@thi.ng/api","@thi.ng/distance","@thi.ng/random","@thi.ng/vectors"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).thi=e.thi||{},e.thi.ng=e.thi.ng||{},e.thi.ng.kMeans={}),e.thi.ng.api,e.thi.ng.distance,e.thi.ng.random,e.thi.ng.vectors)}(this,(function(e,t,n,i,s){"use strict";const r=(e,s,r=n.DIST_SQ,o=i.SYSTEM)=>{const a=s.length;t.assert(a>=e,`insufficient samples for k=${e}`);const h=[o.int()%a],d=[s[h[0]]],l=new Array(a).fill(0).map(((e,t)=>t)),g=r.metric;for(;h.length<e;){let e,t=s.map((e=>r.from(g(e,d[n.argmin(e,d)]))**2));do{e=i.weightedRandom(l,t)()}while(h.includes(e));h.push(e),d.push(s[e])}return h},o=(e,t,i,s)=>{let r=!1;for(let o=0,a=e.length;o<a;o++){const a=n.argmin(e[o],t,s);a!==i[o]&&(i[o]=a,r=!0)}return r},a=(e,t)=>{const n=[];for(let i=0,s=t.length;i<s;i++){const s=t[i];(n[s]||(n[s]={id:s,centroid:e[s],items:[]})).items.push(i)}return n},h=e=>{const t=s.zeroes(e);let n=0;return{update:e=>{s.add(t,t,e),n++},finish:()=>n?s.mulN(t,t,1/n):void 0}};e.initKmeanspp=r,e.kmeans=(e,s,d)=>{let{dist:l,initial:g,maxIter:u,rnd:f,strategy:c}=Object.assign({dist:n.DIST_SQ,maxIter:32,strategy:h},d);const m=s.length,p=s[0].length,y=g||r(e,s,l,f);t.assert(y.length===e,"wrong number of initial centroids");const b=y.map((e=>s[e])),v=[];let S=!0;e:for(;S&&u-- >0;){S=o(s,b,v,l);for(let t=0;t<e;t++){const e=c(p);for(let n=0;n<m;n++)t===v[n]&&e.update(s[n]);const n=e.finish();if(n)b[t]=n;else{const e=y.length;if(i.uniqueIndices(1,m,y,void 0,f),y.length===e)break e;b[t]=s[y[e]],S=!0}}}return a(b,v)},e.means=h,e.meansWgs84=()=>{let e=0,t=0,n=0;return{update:([i,s])=>{e+=i<0?i+360:i,t+=s,n++},finish:()=>{if(n)return e/=n,e>180&&(e-=360),t/=n,[e,t]}}},e.medians=()=>{const e=[];return{update:t=>e.push(t),finish:()=>e.length?s.median([],e):void 0}},Object.defineProperty(e,"__esModule",{value:!0})})); | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@thi.ng/api"),require("@thi.ng/distance"),require("@thi.ng/random"),require("@thi.ng/vectors")):"function"==typeof define&&define.amd?define(["exports","@thi.ng/api","@thi.ng/distance","@thi.ng/random","@thi.ng/vectors"],t):t(((e="undefined"!=typeof globalThis?globalThis:e||self).thi=e.thi||{},e.thi.ng=e.thi.ng||{},e.thi.ng.kMeans={}),e.thi.ng.api,e.thi.ng.distance,e.thi.ng.random,e.thi.ng.vectors)}(this,(function(e,t,n,i,s){"use strict";const r=(e,s,r=n.DIST_SQ,o=i.SYSTEM)=>{const a=s.length;t.assert(a>=e,`insufficient samples for k=${e}`);const h=[o.int()%a],d=[s[h[0]]],l=new Array(a).fill(0).map(((e,t)=>t)),u=r.metric;for(;h.length<e;){let e,t=s.map((e=>r.from(u(e,d[n.argmin(e,d)]))**2));do{e=i.weightedRandom(l,t)()}while(h.includes(e));h.push(e),d.push(s[e])}return h},o=(e,t,i,s)=>{let r=!1;for(let o=0,a=e.length;o<a;o++){const a=n.argmin(e[o],t,s);a!==i[o]&&(i[o]=a,r=!0)}return r},a=(e,t)=>{const n=[];for(let i=0,s=t.length;i<s;i++){const s=t[i];(n[s]||(n[s]={id:s,centroid:e[s],items:[]})).items.push(i)}return n},h=e=>{const t=s.zeroes(e);let n=0;return{update:e=>{s.add(t,t,e),n++},finish:()=>n?s.mulN(t,t,1/n):void 0}};e.initKmeanspp=r,e.kmeans=(e,s,d)=>{let{dist:l,initial:u,maxIter:g,rnd:f,strategy:c}=Object.assign({dist:n.DIST_SQ,maxIter:32,strategy:h},d);const m=s.length,p=s[0].length,y=u||r(e,s,l,f);t.assert(y.length===e,"wrong number of initial centroids");const b=y.map((e=>s[e])),v=[];let S=!0;e:for(;S&&g-- >0;){S=o(s,b,v,l);for(let t=0;t<e;t++){const e=c(p);for(let n=0;n<m;n++)t===v[n]&&e.update(s[n]);const n=e.finish();if(n)b[t]=n;else{const e=y.length;if(i.uniqueIndices(1,m,y,void 0,f),y.length===e)break e;b[t]=s[y[e]],S=!0}}}return a(b,v)},e.means=h,e.meansLatLon=()=>{let e=0,t=0,n=0;return{update:([i,s])=>{e+=i<0?i+360:i,t+=s,n++},finish:()=>{if(n)return e/=n,e>180&&(e-=360),t/=n,[e,t]}}},e.medians=()=>{const e=[];return{update:t=>e.push(t),finish:()=>e.length?s.median([],e):void 0}},Object.defineProperty(e,"__esModule",{value:!0})})); |
{ | ||
"name": "@thi.ng/k-means", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "Configurable k-means & k-medians (with k-means++ initialization) for n-D vectors", | ||
@@ -53,5 +53,5 @@ "module": "./index.js", | ||
"@thi.ng/api": "^7.1.4", | ||
"@thi.ng/distance": "^0.3.0", | ||
"@thi.ng/distance": "^0.3.1", | ||
"@thi.ng/random": "^2.4.0", | ||
"@thi.ng/vectors": "^5.3.0" | ||
"@thi.ng/vectors": "^6.0.0" | ||
}, | ||
@@ -80,3 +80,3 @@ "files": [ | ||
}, | ||
"gitHead": "aa62376d4f1da5e28570659120b3723d3856d964" | ||
"gitHead": "8fcf77133e53fe5871ea12030b9b079cca315d2d" | ||
} |
@@ -44,3 +44,3 @@ <!-- This file is generated - DO NOT EDIT! --> | ||
Package sizes (gzipped, pre-treeshake): ESM: 796 bytes / CJS: 856 bytes / UMD: 972 bytes | ||
Package sizes (gzipped, pre-treeshake): ESM: 928 bytes / CJS: 987 bytes / UMD: 1.07 KB | ||
@@ -61,3 +61,3 @@ ## Dependencies | ||
```ts | ||
import { kmeans } from "@thi.ng/k-means"; | ||
import { kmeans, meansLatLon } from "@thi.ng/k-means"; | ||
import { HAVERSINE_LATLON } from "@thi.ng/distance"; | ||
@@ -84,4 +84,9 @@ | ||
items.map((x) => x.latlon), | ||
// use custom distance function (default: DIST_SQ) | ||
{ dist: HAVERSINE_LATLON } | ||
{ | ||
// custom centroid calc for geo locations | ||
// https://docs.thi.ng/umbrella/k-means/modules.html#meanslatlon | ||
strategy: meansLatLon, | ||
// custom distance function for geo location (default: DIST_SQ) | ||
dist: HAVERSINE_LATLON | ||
} | ||
); | ||
@@ -88,0 +93,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
44105
405
119
- Removed@thi.ng/math@3.4.0(transitive)
- Removed@thi.ng/vectors@5.3.0(transitive)
Updated@thi.ng/distance@^0.3.1
Updated@thi.ng/vectors@^6.0.0