Skip to content

Commit e4c7e65

Browse files
committed
add arithmetic methods to groupby
1 parent eb1d10a commit e4c7e65

1 file changed

Lines changed: 113 additions & 5 deletions

File tree

src/danfojs-base/aggregators/groupby.ts

Lines changed: 113 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ export default class Groupby {
2424
colIndex: ArrayType1D
2525
groupDict?: any
2626
groupColNames?: Array<string>
27+
keyToValue: {
28+
[key: string] : ArrayType1D
29+
} = {}
2730

2831
constructor(keyCol: ArrayType1D, data: ArrayType2D | null, columnName: ArrayType1D, colDtype:ArrayType1D, colIndex: ArrayType1D) {
2932

@@ -80,6 +83,9 @@ export default class Groupby {
8083

8184
group(): Groupby{
8285
const self = this
86+
let keyToValue:{
87+
[key: string] : ArrayType1D
88+
} = {}
8389
const group = this.data?.reduce((prev: any, current)=>{
8490
let indexes= []
8591
for(let i in self.colIndex) {
@@ -88,6 +94,10 @@ export default class Groupby {
8894
}
8995
let index = indexes.join('-')
9096

97+
if(!keyToValue[index]) {
98+
keyToValue[index] = indexes
99+
}
100+
91101
if(prev[index]) {
92102
let data = prev[index]
93103
for (let i in self.columnName) {
@@ -105,6 +115,7 @@ export default class Groupby {
105115

106116
}, {})
107117
this.colDict = group
118+
this.keyToValue = keyToValue
108119
return this
109120
}
110121

@@ -139,11 +150,12 @@ export default class Groupby {
139150
)
140151
gp.colDict = colDict
141152
gp.groupColNames = colNames as Array<string>
153+
gp.keyToValue = this.keyToValue
142154

143155
return gp
144156
}
145157

146-
arithemetic(operation: {[key: string] : string} | string): { [key: string ]: {} } {
158+
arithemetic(operation: {[key: string] : Array<string> | string} | string): { [key: string ]: {} } {
147159

148160
const opsName = [ "mean", "sum", "count", "mode", "std", "var", "cumsum", "cumprod",
149161
"cummax", "cummin", "median" , "min"];
@@ -154,9 +166,18 @@ export default class Groupby {
154166
} else {
155167
Object.keys(operation).forEach((key)=>{
156168
let ops = operation[key]
157-
if (!opsName.includes(ops)) {
158-
throw new Error(`group operation: ${ops} for column ${key} is not valid`)
169+
if(Array.isArray(ops)) {
170+
for(let op of ops) {
171+
if (!opsName.includes(op)) {
172+
throw new Error(`group operation: ${op} for column ${key} is not valid`)
173+
}
174+
}
175+
} else {
176+
if (!opsName.includes(ops)) {
177+
throw new Error(`group operation: ${ops} for column ${key} is not valid`)
178+
}
159179
}
180+
160181
})
161182
}
162183
let colDict: { [key: string ]: {} } = {...this.colDict}
@@ -171,10 +192,19 @@ export default class Groupby {
171192
if (colDtype === "string") throw new Error(`Can't perform math operation on column ${colName}`)
172193

173194
if (typeof operation === "string") {
174-
colVal[colName] = this.groupMathLog(keyVal[colName], operation)
195+
let colName2 = `${colName}_${operation}`
196+
colVal[colName2] = this.groupMathLog(keyVal[colName], operation)
175197
}
176198
else {
177-
colVal[colName] = this.groupMathLog(keyVal[colName], operation[colName])
199+
if(Array.isArray(operation[colName])) {
200+
for(let ops of operation[colName]) {
201+
colVal[colName] = this.groupMathLog(keyVal[colName],ops)
202+
}
203+
} else {
204+
let ops: string = operation[colName] as string
205+
colVal[colName] = this.groupMathLog(keyVal[colName], ops)
206+
}
207+
178208
}
179209
}
180210
colDict[key] = colVal
@@ -269,4 +299,82 @@ export default class Groupby {
269299
}
270300
return data
271301
}
302+
303+
toDataFrame(colDict: { [key: string ]: {} }): DataFrame {
304+
let data: { [key: string ]: ArrayType1D } = {}
305+
306+
for(let key of Object.keys(colDict)) {
307+
let value = colDict[key]
308+
let keyDict: { [key: string ]: ArrayType1D } = {}
309+
let oneValue = Object.values(value)[0] as ArrayType1D
310+
let valueLen = oneValue.length
311+
for(let key1 in this.keyCol) {
312+
let keyName = this.keyCol[key1] as string
313+
let keyValue = this.keyToValue[key][key1]
314+
keyDict[keyName] = Array(valueLen).fill(keyValue)
315+
}
316+
let combine: { [key: string ]: ArrayType1D } = {...keyDict, ...value}
317+
if(Object.keys(data).length < 1) {
318+
data = combine
319+
} else {
320+
for(let dataKey of Object.keys(data)) {
321+
let dataValue = combine[dataKey] as ArrayType1D
322+
data[dataKey] = [...data[dataKey], ...dataValue]
323+
}
324+
}
325+
}
326+
return new DataFrame(data)
327+
}
328+
329+
operations(ops: string): DataFrame {
330+
if (!this.groupColNames) {
331+
let colGroup = this.col(undefined)
332+
let colDict = colGroup.arithemetic(ops)
333+
let df = colGroup.toDataFrame(colDict)
334+
return df
335+
}
336+
let colDict = this.arithemetic(ops)
337+
let df = this.toDataFrame(colDict)
338+
return df
339+
}
340+
341+
count() {
342+
return this.operations("count")
343+
}
344+
345+
sum(){
346+
return this.operations("sum")
347+
}
348+
349+
var(){
350+
return this.operations("var")
351+
}
352+
353+
mean(){
354+
return this.operations("mean")
355+
}
356+
357+
cumsum(){
358+
return this.operations("cumsum")
359+
}
360+
361+
cummax(){
362+
return this.operations("cummax")
363+
}
364+
365+
cumprod(){
366+
return this.operations("cumprod")
367+
}
368+
369+
cummin(){
370+
return this.operations("cummin")
371+
}
372+
373+
max(){
374+
return this.operations("max")
375+
}
376+
377+
min(){
378+
return this.operations("min")
379+
}
272380
}

0 commit comments

Comments
 (0)