Skip to content

Commit 358540e

Browse files
author
minjk-bl
committed
Add pivot_table to Reshape
1 parent d5d56bf commit 358540e

File tree

3 files changed

+122
-13
lines changed

3 files changed

+122
-13
lines changed

html/m_apps/reshape.html

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<label for="vp_rsType" class="vp-orange-text w100">Reshape Type</label>
55
<select id="vp_rsType">
66
<option value="pivot" selected="">pivot</option>
7+
<option value="pivot_table" selected="">pivot table</option>
78
<option value="melt">melt</option>
89
</select>
910
</div>
@@ -28,6 +29,24 @@
2829
<input type="text" id="vp_rsValues" placeholder="Values key" readonly="">
2930
</div>
3031
</div>
32+
<div class="vp-rs-type-box pivot_table">
33+
<div>
34+
<label for="vp_rsIndex" class="w100">Index</label>
35+
<input type="text" id="vp_rsIndex" placeholder="Index key" readonly="">
36+
</div>
37+
<div>
38+
<label for="vp_rsColumns" class="w100">Columns</label>
39+
<input type="text" id="vp_rsColumns" placeholder="Columns key" readonly="">
40+
</div>
41+
<div>
42+
<label for="vp_rsValues" class="w100">Values</label>
43+
<input type="text" id="vp_rsValues" placeholder="Values key" readonly="">
44+
</div>
45+
<div>
46+
<label for="vp_rsAggfunc" class="w100" title="aggfunc">Aggregate</label>
47+
<input type="text" id="vp_rsAggfunc" placeholder="Aggregate functions" readonly="">
48+
</div>
49+
</div>
3150
<div class="vp-rs-type-box melt" style="display:none;">
3251
<div>
3352
<label for="vp_rsIdVars" class="w100">Id</label>

js/com/component/MultiSelector.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,14 @@ define([
6161
// configuration
6262
this.config = this.state;
6363

64-
var { mode, type, parent, selectedList=[], includeList=[], excludeList=[] } = this.config;
65-
this.mode = mode; // variable / columns / index / ndarray0 / ndarray1
64+
var { mode, type, parent, dataList=[], selectedList=[], includeList=[], excludeList=[] } = this.config;
65+
this.mode = mode; // variable / columns / index / ndarray0 / ndarray1 / methods / data(given data)
6666
this.parent = parent;
6767
this.selectedList = selectedList;
6868
this.includeList = includeList;
6969
this.excludeList = excludeList;
7070

71-
this.dataList = [];
71+
this.dataList = dataList; // [ { value, code, type }, ... ]
7272
this.pointer = { start: -1, end: -1 };
7373

7474
var that = this;
@@ -99,6 +99,9 @@ define([
9999
that._executeCallback(dataList);
100100
});
101101
break;
102+
case 'data':
103+
that._executeCallback(this.dataList);
104+
break;
102105
}
103106
}
104107

js/m_apps/Reshape.js

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ define([
3838
pivot: {
3939
index: [],
4040
columns: [],
41-
values: []
41+
values: [],
42+
aggfunc: []
4243
},
4344
melt: {
4445
idVars: [],
@@ -98,7 +99,7 @@ define([
9899
that._resetColumnSelector(that.wrapSelector('#vp_rsValueVars'));
99100

100101
that.state.pivot = {
101-
index: [], columns: [], values: []
102+
index: [], columns: [], values: [], aggfunc: []
102103
};
103104
that.state.melt = {
104105
idVars: [], valueVars: []
@@ -116,13 +117,8 @@ define([
116117
var type = $(this).val();
117118
that.state.type = type;
118119
// change visibility
119-
if (type == 'pivot') {
120-
$(that.wrapSelector('.vp-rs-type-box.melt')).hide();
121-
$(that.wrapSelector('.vp-rs-type-box.pivot')).show();
122-
} else {
123-
$(that.wrapSelector('.vp-rs-type-box.pivot')).hide();
124-
$(that.wrapSelector('.vp-rs-type-box.melt')).show();
125-
}
120+
$(that.wrapSelector('.vp-rs-type-box')).hide();
121+
$(that.wrapSelector('.vp-rs-type-box.' + type)).show();
126122

127123
// clear user option
128124
$(that.wrapSelector('#vp_rsUserOption')).val('');
@@ -168,6 +164,19 @@ define([
168164
that.openColumnSelector(targetVariable, $(that.wrapSelector('#vp_rsValues')), 'Select columns', excludeList);
169165
});
170166

167+
// aggfunc change event
168+
$(document).on('change', this.wrapSelector('#vp_rsAggfunc'), function(event) {
169+
var colList = event.dataList;
170+
that.state.pivot.aggfunc = colList;
171+
});
172+
173+
// aggfunc select button event
174+
$(document).on('click', this.wrapSelector('#vp_rsAggfunc'), function() {
175+
var targetVariable = [ that.state.variable ];
176+
var excludeList = that.state.pivot.aggfunc.map(obj => obj.code);
177+
that.openMethodSelector(targetVariable, $(that.wrapSelector('#vp_rsAggfunc')), 'Select columns', excludeList);
178+
});
179+
171180
// id vars change event
172181
$(document).on('change', this.wrapSelector('#vp_rsIdVars'), function(event) {
173182
var colList = event.dataList;
@@ -344,13 +353,39 @@ define([
344353
* @param {Array<string>} previousList previous selected columns
345354
* @param {Array<string>} excludeList columns to exclude
346355
*/
347-
renderColumnSelector(targetVariable, previousList, excludeList) {
356+
renderColumnSelector(targetVariable, previousList, excludeList) {
348357
this.popup.ColSelector = new MultiSelector(
349358
this.wrapSelector('.vp-inner-popup-body'),
350359
{ mode: 'columns', parent: targetVariable, selectedList: previousList, excludeList: excludeList }
351360
);
352361
}
353362

363+
/**
364+
* Render method selector using MultiSelector module
365+
* @param {Array<string>} previousList previous selected methods
366+
* @param {Array<string>} excludeList methods to exclude
367+
*/
368+
renderMethodSelector(targetVariable, previousList, excludeList) {
369+
let methodList = [
370+
{ value: 'count', code: "'count'" },
371+
{ value: 'first', code: "'first'" },
372+
{ value: 'last', code: "'last'" },
373+
{ value: 'size', code: "'size'" },
374+
{ value: 'std', code: "'std'" },
375+
{ value: 'sum', code: "'sum'" },
376+
{ value: 'max', code: "'max'" },
377+
{ value: 'mean', code: "'mean'" },
378+
{ value: 'median', code: "'median'" },
379+
{ value: 'min', code: "'min'" },
380+
{ value: 'quantile', code: "'quantile'" },
381+
];
382+
383+
this.popup.ColSelector = new MultiSelector(
384+
this.wrapSelector('.vp-inner-popup-body'),
385+
{ mode: 'data', parent: targetVariable, dataList: methodList, selectedList: previousList, excludeList: excludeList }
386+
);
387+
}
388+
354389
/**
355390
* Load variable list (dataframe)
356391
*/
@@ -422,6 +457,45 @@ define([
422457
}
423458
}
424459

460+
} else if (type == 'pivot_table') {
461+
//================================================================
462+
// pivot_table
463+
//================================================================
464+
// index (optional)
465+
if (pivot.index && pivot.index.length > 0) {
466+
if (pivot.index.length == 1) {
467+
options.push(com_util.formatString("index={0}", pivot.index[0].code));
468+
} else {
469+
options.push(com_util.formatString("index=[{0}]", pivot.index.map(col => col.code).join(',')));
470+
}
471+
}
472+
473+
// columns
474+
if (pivot.columns && pivot.columns.length > 0) {
475+
if (pivot.columns.length == 1) {
476+
options.push(com_util.formatString("columns={0}", pivot.columns[0].code));
477+
} else {
478+
options.push(com_util.formatString("columns=[{0}]", pivot.columns.map(col => col.code).join(',')));
479+
}
480+
}
481+
482+
// values (optional)
483+
if (pivot.values && pivot.values.length > 0) {
484+
if (pivot.values.length == 1) {
485+
options.push(com_util.formatString("values={0}", pivot.values[0].code));
486+
} else {
487+
options.push(com_util.formatString("values=[{0}]", pivot.values.map(col => col.code).join(',')));
488+
}
489+
}
490+
491+
// aggfunc
492+
if (pivot.aggfunc && pivot.aggfunc.length > 0) {
493+
if (pivot.aggfunc.length == 1) {
494+
options.push(com_util.formatString("aggfunc={0}", pivot.aggfunc[0].code));
495+
} else {
496+
options.push(com_util.formatString("aggfunc=[{0}]", pivot.aggfunc.map(col => col.code).join(',')));
497+
}
498+
}
425499
} else {
426500
//================================================================
427501
// melt
@@ -511,6 +585,19 @@ define([
511585
this.openInnerPopup(title);
512586
}
513587

588+
openMethodSelector(targetVariable, targetSelector, title='Select methods', excludeList=[]) {
589+
this.popup.targetVariable = targetVariable;
590+
this.popup.targetSelector = targetSelector;
591+
var previousList = this.popup.targetSelector.data('list');
592+
if (previousList) {
593+
previousList = previousList.map(col => col.code)
594+
}
595+
this.renderMethodSelector(targetVariable, previousList, excludeList);
596+
597+
// set title
598+
this.openInnerPopup(title);
599+
}
600+
514601
handleInnerOk() {
515602
// ok input popup
516603
var dataList = this.popup.ColSelector.getDataList();

0 commit comments

Comments
 (0)