Skip to content

Commit 827ada1

Browse files
committed
Add group arithmetic operations
1 parent eda783e commit 827ada1

1 file changed

Lines changed: 127 additions & 4 deletions

File tree

src/danfojs-base/aggregators/groupby.ts

Lines changed: 127 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Console } from "console";
22
import DataFrame from "../core/frame"
33
import { ArrayType1D, ArrayType2D } from "../shared/types"
4+
import { variance, std, median, mode, mean } from 'mathjs';
45
import Utils from "../shared/utils";
56
import concat from "../transformers/concat"
67

@@ -108,9 +109,7 @@ export default class Groupby {
108109
}
109110

110111
col(colNames: ArrayType1D | undefined): Groupby {
111-
type f = {
112-
[key: string]: []
113-
}
112+
114113
if (typeof colNames === "undefined") {
115114
colNames = this.columnName.filter((_, index)=>{
116115
return !this.colIndex.includes(index)
@@ -144,5 +143,129 @@ export default class Groupby {
144143
return gp
145144
}
146145

147-
146+
arithemetic(operation: {[key: string] : string} | string): { [key: string ]: {} } {
147+
148+
const opsName = [ "mean", "sum", "count", "mode", "std", "var", "cumsum", "cumprod",
149+
"cummax", "cummin", "median" ];
150+
if (typeof operation === "string" ) {
151+
if (!opsName.includes(operation)) {
152+
throw new Error(`group operation: ${operation} is not valid`)
153+
}
154+
} else {
155+
Object.keys(operation).forEach((key)=>{
156+
let ops = operation[key]
157+
if (!opsName.includes(ops)) {
158+
throw new Error(`group operation: ${ops} for column ${key} is not valid`)
159+
}
160+
})
161+
}
162+
let colDict: { [key: string ]: {} } = {...this.colDict}
163+
for(const [key, values] of Object.entries(this.colDict)) {
164+
let colVal: { [key: string ]: Array<number> } = {}
165+
let keyVal: any = {...values}
166+
for(let colKey in this.groupColNames) {
167+
let colName = this.groupColNames[colKey] as string
168+
let colIndex = this.columnName.indexOf(colName)
169+
let colDtype = this.colDtype[colIndex]
170+
if (colDtype === "string") throw new Error(`Can't perform math operation on column ${colName}`)
171+
172+
if (typeof operation === "string") {
173+
colVal[key] = this.groupMathLog(keyVal[colName], operation)
174+
}
175+
else {
176+
colVal[key] = this.groupMathLog(keyVal[colName], operation[colName])
177+
}
178+
}
179+
colDict[key] = colVal
180+
}
181+
return colDict
182+
}
183+
184+
groupMathLog(colVal: Array<number>, ops: string): Array<number>{
185+
let data = []
186+
switch(ops) {
187+
case "max":
188+
let max = colVal.reduce((prev, curr)=> {
189+
if (prev > curr) {
190+
return prev
191+
}
192+
return curr
193+
})
194+
data.push(max)
195+
break;
196+
case "min":
197+
let min = colVal.reduce((prev, curr)=> {
198+
if (prev < curr) {
199+
return prev
200+
}
201+
return curr
202+
})
203+
data.push(min)
204+
break;
205+
case "sum":
206+
let sum = colVal.reduce((prev, curr)=> {
207+
return prev + curr
208+
})
209+
data.push(sum)
210+
break;
211+
case "count":
212+
data.push(colVal.length)
213+
break;
214+
case "mean":
215+
let sumMean = colVal.reduce((prev, curr)=> {
216+
return prev + curr
217+
})
218+
data.push(sumMean / colVal.length)
219+
break;
220+
case "std":
221+
data.push(std(colVal))
222+
break;
223+
case "var":
224+
data.push(variance(colVal))
225+
break;
226+
case "median":
227+
data.push(median(colVal))
228+
break;
229+
case "mode":
230+
data.push(mode(colVal))
231+
break;
232+
case "cumsum":
233+
colVal.reduce((prev, curr) => {
234+
let sum = prev + curr
235+
data.push(sum)
236+
return sum
237+
}, 0)
238+
break;
239+
case "cummin":
240+
data = [colVal[0]]
241+
colVal.slice(1,).reduce((prev, curr)=>{
242+
if (prev < curr) {
243+
data.push(prev)
244+
return prev
245+
}
246+
data.push(curr)
247+
return curr
248+
}, data[0])
249+
break;
250+
case "cummax":
251+
data = [colVal[0]]
252+
colVal.slice(1,).reduce((prev, curr)=> {
253+
if (prev > curr) {
254+
data.push(prev)
255+
return prev
256+
}
257+
data.push(curr)
258+
return curr
259+
}, data[0])
260+
break;
261+
case "cumprod":
262+
colVal.reduce((prev, curr) => {
263+
let sum = prev * curr
264+
data.push(sum)
265+
return sum
266+
}, 1)
267+
break;
268+
}
269+
return data
270+
}
148271
}

0 commit comments

Comments
 (0)