WCluster.mjs

import WPCAMat from './WPCAMat.mjs'
import WClusterCore from './WClusterCore.mjs'


/**
 * 數據主成分分析(Principal Component Analysis, PCA)
 *
 * @param {Array} data 輸入數據陣列
 * @param {Object} [opt={}] 輸入設定物件,預設{}
 * @param {Boolean} [opt.scale=true] 輸入是否對數據正規化布林值,預設true
 * @param {Number} [opt.nCompNIPALS=2] 輸入指定降維的維度整數,不能超過數據的維度(各列有效元素數量),預設2
 * @return {Promise} 回傳Promise,resolve回傳指定維數數值的陣列,reject回傳錯誤訊息
 * @example
 */
async function PCA(data, opt = {}) {
    return WPCAMat(data, opt)
}


/**
 * 針對數據陣列做分群
 *
 * @param {Array} data 輸入數據陣列,可輸入純數據陣列(mat)或物件陣列(ltdt)
 * @param {Object} [opt={}] 輸入設定物件,預設{}
 * @param {Number} [opt.kNumber=2] 輸入指定分群數整數,不能超過數據的長度,預設2
 * @param {Number} [opt.nCompNIPALS=2] 輸入指定降維的維度整數,不能超過數據的維度(各列有效元素數量),預設2
 * @param {String} [opt.mode='k-medoids'] 輸入分群方法字串,可為'k-means'、'k-medoids',k-means受初始隨機群中心影響較大,預設'k-medoids'
 * @return {Promise} 回傳Promise,resolve回傳分群後結果物件,keys代表分群有使用到的欄位,ginds代表分群後的指標陣列,gltdt代表分群後的物件陣列,gmat代表分群後且經過PCA處理的數據陣列,其內因是降維後的數據,可例如取最左2欄的數據代表x,y來繪製分群後二維分佈圖,reject回傳錯誤訊息
 * @example
 */
async function cluster(data, opt = {}) {
    try {
        return WClusterCore(data, opt)
    }
    catch (err) {
        return Promise.reject(err)
    }
}


/**
 * 數據主成份分析與分群
 *
 * @return {Object} 回傳物件,其內有PCA與cluster函式,PCA為主成份分析,cluster為分群分析
 * @example
 *
 * async function testPCA() {
 *
 *     let mat = [
 *         [40, 50, 60],
 *         [50, 70, 60],
 *         [80, 70, 90],
 *         [50, 60, 80]
 *     ]
 *     console.log('mat', mat)
 *     // => mat [ [ 40, 50, 60 ], [ 50, 70, 60 ], [ 80, 70, 90 ], [ 50, 60, 80 ] ]
 *
 *     let resMat = await WCluster.PCA(mat, { nCompNIPALS: 2 })
 *     console.log(resMat)
 *     // => [
 *     //   [ -1.704002697669786, 0.43087564048799354 ],
 *     //   [ -0.2509699164590232, -1.1519035967558147 ],
 *     //   [ 1.9913098008410954, 0.23244503334983269 ],
 *     //   [ -0.03633718671228592, 0.48858292291798827 ]
 *     // ]
 *
 *     let mat2 = [
 *         [1040, 50, 60],
 *         [1050, 70, 60],
 *         [1080, 70, 90],
 *         [1050, 60, 80]
 *     ]
 *     console.log('mat2', mat2)
 *     // => mat [ [ 1040, 50, 60 ], [ 1050, 70, 60 ], [ 1080, 70, 90 ], [ 1050, 60, 80 ] ]
 *
 *     let resMat2 = await WCluster.PCA(mat2, { nCompNIPALS: 2 })
 *     console.log(resMat2)
 *     // => [
 *     //   [ -1.704002697669786, 0.43087564048799354 ],
 *     //   [ -0.2509699164590232, -1.1519035967558147 ],
 *     //   [ 1.9913098008410954, 0.23244503334983269 ],
 *     //   [ -0.03633718671228592, 0.48858292291798827 ]
 *     // ]
 *
 *     let mat3 = [
 *         [11040, 50, 60],
 *         [13050, 70, 60],
 *         [15080, 70, 90],
 *         [17050, 60, 80]
 *     ]
 *     console.log('mat3', mat3)
 *     // => mat [ [ 11040, 50, 60 ], [ 13050, 70, 60 ], [ 15080, 70, 90 ], [ 17050, 60, 80 ] ]
 *
 *     let resMat3 = await WCluster.PCA(mat3, { nCompNIPALS: 2 })
 *     console.log(resMat3)
 *     // => [
 *     //   [ -1.8599655569892897, 0.4908764271508211 ],
 *     //   [ -0.3950941652793108, -1.0977355294143445 ],
 *     //   [ 1.3430199944041517, -0.17213692267477554 ],
 *     //   [ 0.912039727864449, 0.778996024938299 ]
 *     // ]
 *
 * }
 * testPCA()
 *     .catch((err) => {
 *         console.log(err)
 *     })
 *
 * async function testCluster() {
 *     let mode = 'k-medoids'
 *
 *     let mat = [
 *         [40, 50, 60],
 *         [50, 70, 60],
 *         [80, 70, 90],
 *         [50, 60, 80]
 *     ]
 *     console.log('mat', mat)
 *     // => mat [ [ 40, 50, 60 ], [ 50, 70, 60 ], [ 80, 70, 90 ], [ 50, 60, 80 ] ]
 *
 *     let resMat = await WCluster.cluster(mat, { mode, kNumber: 2, nCompNIPALS: 2 })
 *     console.log(JSON.stringify(resMat, null, 2))
 *     // => {
 *     //   "keys": null,
 *     //   "ginds": [
 *     //     [ 0, 1, 3 ],
 *     //     [ 2 ]
 *     //   ],
 *     //   "gmat": [
 *     //     [
 *     //       [ -1.704002697669786, 0.43087564048799354 ],
 *     //       [ -0.2509699164590232, -1.1519035967558147 ],
 *     //       [ -0.03633718671228592, 0.48858292291798827 ]
 *     //     ],
 *     //     [
 *     //       [ 1.9913098008410954, 0.23244503334983269 ]
 *     //     ]
 *     //   ],
 *     //   "gltdt": [
 *     //     [
 *     //       [ 40, 50, 60 ],
 *     //       [ 50, 70, 60 ],
 *     //       [ 50, 60, 80 ]
 *     //     ],
 *     //     [
 *     //       [ 80, 70, 90 ]
 *     //     ]
 *     //   ]
 *     // }
 *
 *     let mat2 = [
 *         [1040, 50, 60],
 *         [1050, 70, 60],
 *         [1080, 70, 90],
 *         [1050, 60, 80]
 *     ]
 *     console.log('mat2', mat2)
 *     // => mat [ [ 1040, 50, 60 ], [ 1050, 70, 60 ], [ 1080, 70, 90 ], [ 1050, 60, 80 ] ]
 *
 *     let resMat2 = await WCluster.cluster(mat2, { mode, kNumber: 2, nCompNIPALS: 2 })
 *     console.log(JSON.stringify(resMat2, null, 2))
 *     // => {
 *     //   "keys": null,
 *     //   "ginds": [
 *     //     [ 0, 1, 3 ],
 *     //     [ 2 ]
 *     //   ],
 *     //   "gmat": [
 *     //     [
 *     //       [ -1.704002697669786, 0.43087564048799354 ],
 *     //       [ -0.2509699164590232, -1.1519035967558147 ],
 *     //       [ -0.03633718671228592, 0.48858292291798827 ]
 *     //     ],
 *     //     [
 *     //       [ 1.9913098008410954, 0.23244503334983269 ]
 *     //     ]
 *     //   ],
 *     //   "gltdt": [
 *     //     [
 *     //       [ 1040, 50, 60 ],
 *     //       [ 1050, 70, 60 ],
 *     //       [ 1050, 60, 80 ]
 *     //     ],
 *     //     [
 *     //       [ 1080, 70, 90 ]
 *     //     ]
 *     //   ]
 *     // }
 *
 *     let mat3 = [
 *         [11040, 50, 60],
 *         [13050, 70, 60],
 *         [15080, 70, 90],
 *         [17050, 60, 80]
 *     ]
 *     console.log('mat3', mat3)
 *     // => mat [ [ 11040, 50, 60 ], [ 13050, 70, 60 ], [ 15080, 70, 90 ], [ 17050, 60, 80 ] ]
 *
 *     let resMat3 = await WCluster.cluster(mat3, { mode, kNumber: 2, nCompNIPALS: 2 })
 *     console.log(JSON.stringify(resMat3, null, 2))
 *     // => {
 *     //   "keys": null,
 *     //   "ginds": [
 *     //     [ 1, 2, 3 ],
 *     //     [ 0 ]
 *     //   ],
 *     //   "gmat": [
 *     //     [
 *     //       [ -0.3950941652793108, -1.0977355294143445 ],
 *     //       [ 1.3430199944041517, -0.17213692267477554 ],
 *     //       [ 0.912039727864449, 0.778996024938299 ]
 *     //     ],
 *     //     [
 *     //       [ -1.8599655569892897, 0.4908764271508211 ]
 *     //     ]
 *     //   ],
 *     //   "gltdt": [
 *     //     [
 *     //       [ 13050, 70, 60 ],
 *     //       [ 15080, 70, 90 ],
 *     //       [ 17050, 60, 80 ]
 *     //     ],
 *     //     [
 *     //       [ 11040, 50, 60 ]
 *     //     ]
 *     //   ]
 *     // }
 *
 *     let ltdt = [
 *         { name: 'Cameron', a: 40, b: 50, c: 60 },
 *         { name: 'Buckley', a: 50, b: 70, c: 60 },
 *         { name: 'Paul', a: 80, b: 70, c: 90 },
 *         { name: 'Fawcett', a: 50, b: 60, c: 80 },
 *     ]
 *     console.log('ltdt', ltdt)
 *     // => ltdt [
 *     //     { name: 'Cameron', a: 40, b: 50, c: 60 },
 *     //     { name: 'Buckley', a: 50, b: 70, c: 60 },
 *     //     { name: 'Paul', a: 80, b: 70, c: 90 },
 *     //     { name: 'Fawcett', a: 50, b: 60, c: 80 }
 *     // ]
 *
 *     let resLtdt = await WCluster.cluster(ltdt, { mode, kNumber: 2, nCompNIPALS: 2 })
 *     console.log(JSON.stringify(resLtdt, null, 2))
 *     // => {
 *     //   "keys": [ "a", "b", "c" ],
 *     //   "ginds": [
 *     //     [ 0, 1, 3 ],
 *     //     [ 2 ]
 *     //   ],
 *     //   "gmat": [
 *     //     [
 *     //       [ -1.704002697669786, 0.43087564048799354 ],
 *     //       [ -0.2509699164590232, -1.1519035967558147 ],
 *     //       [ -0.03633718671228592, 0.48858292291798827 ]
 *     //     ],
 *     //     [
 *     //       [ 1.9913098008410954, 0.23244503334983269 ]
 *     //     ]
 *     //   ],
 *     //   "gltdt": [
 *     //     [
 *     //       { "name": "Cameron", "a": 40, "b": 50, "c": 60 },
 *     //       { "name": "Buckley", "a": 50, "b": 70, "c": 60 },
 *     //       { "name": "Fawcett", "a": 50, "b": 60, "c": 80 }
 *     //     ],
 *     //     [
 *     //       { "name": "Paul", "a": 80, "b": 70, "c": 90 }
 *     //     ]
 *     //   ]
 *     // }
 *
 * }
 * testCluster()
 *     .catch((err) => {
 *         console.log(err)
 *     })
 *
 */
let WCluster = {
    PCA,
    cluster,
}


export default WCluster