UNPKG

jandas

Version:

A very much Pandas-like JavaScript library for data science

303 lines (302 loc) 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const util_1 = require("./util"); const cmm_1 = require("./cmm"); const df_lib_1 = require("./df_lib"); const Index_1 = require("./Index"); const DataFrame_1 = require("./DataFrame"); const stat = require("simple-statistics"); const _ = require("lodash"); const ranks = require("@stdlib/stats-ranks"); const df_lib_2 = require("./df_lib"); class Series { constructor(first, second) { if (_.isUndefined(second)) second = {}; second = _.defaults(second, { name: '', index: new Index_1.default(first.map((_, i) => i)) }); this.values = first; this.shape = this.values.length; this._name = second.name; this._index = second.index instanceof Index_1.default ? second.index : new Index_1.default(second.index); } get index() { return this._index; } set index(vals) { this._index = (0, cmm_1.setIndex)(vals, this.shape); } get name() { return this._name; } set name(val) { this._name = val; // this.nameSetterEffect() } rename(labelMap, inplace = false) { if (inplace) (0, cmm_1._rename)(this.index, labelMap, true); else { const index = (0, cmm_1._rename)(this.index, labelMap, false); return new Series((0, cmm_1.cp)(this.values), { index, name: this.name }); } } p() { const name_str = this.name ? ' ' + this.name : ''; console.log(this.index.values.map(x => x.toString()).join('\t') + '\n' + this.values.map(x => (0, cmm_1._str)(x)).join('\t') + '\n' + `Series (${this.shape})${name_str}`); } _iloc(idx) { switch (true) { case idx === undefined: return new Series((0, cmm_1.cp)(this.values), { index: this.index.cp(), name: this.name }); case (0, util_1.isNum)(idx): util_1.check.iloc.num(idx, this.shape); return this.values[idx]; default: const [vec, new_idx] = (0, cmm_1.vec_loc2)(this.values, this.index.values, idx); const new_index = new Index_1.default(new_idx, this.index.name); return new Series(vec, { index: new_idx, name: this.name }); } } iloc(idx) { idx = (0, util_1._trans_iloc)(idx, this.shape); return this._iloc(idx); } loc(index) { let num_idx; if (_.isNumber(index) || _.isString(index)) num_idx = (0, cmm_1._trans)(this.index, index); else num_idx = (0, cmm_1._trans)(this.index, index); if (_.isNumber(num_idx)) return this._iloc(num_idx); else return this._iloc(num_idx); } _iset(idx, values) { switch (true) { case idx === undefined: util_1.check.iset.rpl.num(values, this.shape); this.values = (0, cmm_1.cp)(values); break; case (0, util_1.isVal)(idx): util_1.check.iloc.num(idx, this.shape); this.values[idx] = values; break; default: (0, cmm_1.vec_set)(this.values, values, idx); } } iset(first, second) { if (second === undefined) { this._iset(undefined, first); } else { first = (0, util_1._trans_iloc)(first, this.shape); this._iset(first, second); } } set(first, second) { if (second === undefined) { this._iset(undefined, first); } else { if ((0, util_1.isVal)(first) && !this.index.has(first)) this.push(second, first); else { if (first instanceof Index_1.default || first instanceof Series) first = first.values; // differs from pandas with the following // code annotated. See Series.test.tsx // line 320. // if(isNumArr(first)|| isStrArr(first)) // check.set.index.uniq(this.index) if ((0, util_1.isNum)(first) || (0, util_1.isStr)(first)) { const pos = this.index.mp.get(first); if ((0, util_1.isArr)(pos) && !(0, util_1.isArr)(second)) { second = Array.from(Array(pos.length).keys()).map(_ => second); } } const num_idx = (0, cmm_1._trans)(this.index, first); this._iset(num_idx, second); } } } push(val, name = '') { this.values.push(val); this.index.values.push(name); this.shape += 1; } insert(idx, val, name = '') { util_1.check.iloc.num(idx, this.shape); this.values.splice(idx, 0, val); this.index.insert(idx, name); this.shape += 1; } drop(labels) { labels = (0, util_1.isArr)(labels) ? labels : [labels]; const labels2 = labels; const new_idx = (0, util_1.range)(this.index.shape).filter(i => !labels2.includes(this.index.values[i])); return this.iloc(new_idx); } // drop_duplicates_by_index():Series<T>{ // return drop_duplicates_by_index(this) // } drop_duplicates(keep = 'first') { const new_idx = (0, cmm_1.duplicated)(this.values, keep); return this.loc(new_idx.map(x => !x)); } bool(expr) { return this.b(expr); } b(expr, __ctx__) { // console.log(__ctx__) const newExpr = (0, cmm_1.addCtx)(expr, __ctx__); return this.values.map(x => eval(newExpr)); } query(expr, ctx) { return this.q(expr, ctx); } q(expr, ctx) { const bidx = this.b(expr, ctx); return this.loc(bidx); } sort_values(ascending = true) { const idx = (0, df_lib_1._sortIndices)(this.values, false, ascending); return this.iloc(idx); } value_counts() { // only work if values are string or number const mp = new Map; this.values.forEach((e => { const e2 = e; if (!mp.has(e2)) mp.set(e2, 0); mp.set(e2, mp.get(e2) + 1); })); const arr = []; mp.forEach((count, key) => { arr.push([key, count]); }); const df = new DataFrame_1.default(arr, { columns: ['value', 'count'] }); const ss = df.sort_values('count', { ascending: false }).set_index('value').loc(null, 'count'); ss.name = ''; ss.index.name = ''; return ss; } op(opStr, ss) { if (_.isUndefined(ss)) { let vals; if (_.isString(opStr)) vals = this.values.map(x => eval(opStr)); else vals = this.values.map(x => opStr(x)); return new Series(vals, { index: this.index, name: this.name }); } else if ((ss instanceof Series) && this.index.is_unique() && ss.index.is_unique()) { util_1.check.op.index(this.index, ss.index); const vals = []; this.index.values.forEach((idx) => { const x = this.loc(idx); const y = ss.loc(idx); const val = _.isString(opStr) ? eval(opStr) : opStr(x, y); vals.push(val); }); return new Series(vals, this.index); } else { if (ss instanceof Series) { util_1.check.op.index(this.index, ss.index); util_1.check.op.indexSame(this.index, ss.index); ss = ss.values; } util_1.check.op.values(this.index, ss); const vals = []; this.values.forEach((x, i) => { const y = ss[i]; const val = _.isString(opStr) ? eval(opStr) : opStr(x, y); vals.push(val); }); return new Series(vals, this.index); } } unique() { return _.uniq(this.values); } rank(options = {}) { const vals = ranks(this.values, options); return new Series(vals, { index: this.index, name: this.name }); } change(op_str, periods = 1) { const df = new DataFrame_1.default(this.values.map(x => [x]), { index: this.index.cp(), columns: [this.name] }); const cf = df.change(op_str, { periods: periods }); return cf.iloc(null, 0); } diff(periods = 1) { return this.change('x-y', periods); } pct_change(periods = 1) { return this.change('(x-y)/y', periods); } rolling(window, { min_periods = undefined, center = false, closed = 'right', step = 1 } = {}) { const df = new DataFrame_1.default(this.values.map(x => [x]), { index: this.index.cp(), columns: [this.name] }); const roll = new df_lib_2.SeriesRolling(df, window, min_periods, center, closed, step); return roll; } isna() { return this.op('_.isNil(x) || _.isNaN(x)'); } reduce(func) { return func(this.values); } min() { return stat.min(this.values); } max() { return stat.max(this.values); } sum() { return stat.sum(this.values); } mean() { return stat.mean(this.values); } mode() { return stat.mode(this.values); } median() { return stat.median(this.values); } // cumsum(){ // return d3.cumsum(this.values as number[]) // } std() { return stat.sampleStandardDeviation(this.values); } var() { return stat.sampleVariance(this.values); } prod() { return stat.product(this.values); } to_raw(copy = true) { if (copy) return { values: (0, cmm_1.cp)(this.values), name: this.name, index: this.index.to_raw() }; else return { values: this.values, name: this.name, index: this.index.to_raw(copy) }; } } exports.default = Series;