UNPKG

w-statistic

Version:
164 lines (138 loc) 4.65 kB
import get from 'lodash-es/get.js' import each from 'lodash-es/each.js' import size from 'lodash-es/size.js' import cloneDeep from 'lodash-es/cloneDeep.js' import isarr from 'wsemi/src/isarr.mjs' import isp0int from 'wsemi/src/isp0int.mjs' import cint from 'wsemi/src/cint.mjs' import cdbl from 'wsemi/src/cdbl.mjs' import arrAverage from './arrAverage.mjs' /** * 計算陣列內有效數字之移動平均值 * * Unit Test: {@link https://github.com/yuda-lyu/w-statistic/blob/master/test/arrMovingAverage.test.js Github} * @memberOf w-statistic * @param {Array} arr 輸入陣列,只提取有效數字(或為字串的數字)進行計算 * @param {Object} [opt={}] 輸入設定物件,預設{} * @param {Integer} [opt.selectCountHalf=2] 輸入上下取點數整數,總取點數為2*selectCountHalf+1,預設2(取5點) * @returns {Array} 回傳移動平均值陣列 * @example * * let arr * * arr = ['abc', '-2.5', -2.5, '-1', -1, '-0.1', -0.1, '0', 0, '0.1', 0.1, '1', 1, '2.5', 2.5, 22.5, 'xyz'] * console.log(arrMovingAverage(arr)) * // => [ * // -2.5, -2, * // -1.75, -1.42, * // -0.9399999999999998, -0.44000000000000006, * // -0.24000000000000005, -0.02, * // 0.02, 0.24, * // 0.44000000000000006, 0.9400000000000001, * // 1.42, 5.9, * // 7.125, 9.166666666666666, * // 12.5 * // ] * * arr = ['abc', '0', 0, '0.1', 0.1, '1', 1, '2.5', 2.5, 22.5, 'xyz'] * console.log(arrMovingAverage(arr, { selectCountHalf: 1 })) * // => [ * // 0, * // 0, * // 0.03333333333333333, * // 0.06666666666666667, * // 0.39999999999999997, * // 0.7000000000000001, * // 1.5, * // 2, * // 9.166666666666666, * // 12.5, * // 22.5 * // ] * */ function arrMovingAverage(arr, opt = {}) { //check if (!isarr(arr)) { return [] } if (size(arr) === 0) { return [] } //selectCountHalf let selectCountHalf = get(opt, 'selectCountHalf') if (!isp0int(selectCountHalf)) { selectCountHalf = 2 } selectCountHalf = cint(selectCountHalf) //mode let mode = get(opt, 'mode', '') if (mode !== 'PMA' && mode !== 'SMA' && mode !== 'EMA') { mode = 'PMA' } //n let n = size(arr) //check if (n === 0) { return [] } //rs let rs = cloneDeep(arr) //arrAverage each(arr, (v, k) => { let r = 0 if (mode === 'PMA') { //kStart, kEnd let kStart = k - selectCountHalf kStart = Math.max(kStart, 0) kStart = Math.min(kStart, n - 1) let kEnd = Math.max(k + selectCountHalf, 0) kEnd = Math.max(kEnd, 0) kEnd = Math.min(kEnd, n - 1) // console.log('mode', mode) // console.log('kStart', kStart) // console.log('kEnd', kEnd) //arrt let arrt = [] for (let i = kStart; i <= kEnd; i++) { arrt.push(arr[i]) } //arrAverage r = arrAverage(arrt) // console.log(k, kStart, kEnd, 'arrt', arrt, 'avg', r) } else if (mode === 'SMA') { //kStart, kEnd let kStart = k - (selectCountHalf - 1) //-1是因為selectCountHalf要把當前點也算進去 kStart = Math.max(kStart, 0) kStart = Math.min(kStart, n - 1) let kEnd = k // console.log('mode', mode) // console.log('kStart', kStart) // console.log('kEnd', kEnd) //arrt let arrt = [] for (let i = kStart; i <= kEnd; i++) { arrt.push(arr[i]) } // console.log('size(arrt)', size(arrt)) //arrAverage r = arrAverage(arrt) // console.log(k, kStart, kEnd, 'arrt', arrt, 'SMA', r) } else if (mode === 'EMA') { if (k === 0) { r = cdbl(v) } else { let _ema = get(rs, k - 1) //前個ema r = (_ema * (selectCountHalf - 1) + v * 2) / (selectCountHalf + 1) } // console.log(k, kStart, kEnd, 'arrt', arrt, 'EMA', r) } //save rs[k] = r }) return rs } export default arrMovingAverage