Skip to content

Commit 8235e0a

Browse files
author
minjk-bl
committed
Add Sort values to Seaborn app
1 parent 5be1ef5 commit 8235e0a

File tree

3 files changed

+153
-23
lines changed

3 files changed

+153
-23
lines changed

html/m_visualize/seaborn.html

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,26 @@
118118
<label><input type="checkbox" id="showValues" class="vp-state"/><span>Show values</span></label>
119119
<input type="number" id="showValuesPrecision" class="vp-state" placeholder="Type precision (0 ~ 5)" min="0" max="5"/>
120120
</div>
121+
<div class="vp-grid-col-p50 sb-option" style="grid-column-start: 1;grid-column-end: 3;">
122+
<div class="vp-grid-box">
123+
<label class="vp-bold">Sort values by
124+
<select id="sortBy" class="vp-state vp-select" style="width: 75px;height:25px;">
125+
<option value="y">y axis</option>
126+
<option value="x">x axis</option>
127+
</select>
128+
</label>
129+
<select id="sortType" class="vp-state">
130+
<option value="">No sorting</option>
131+
<option value="descending">Sort in descending order</option>
132+
<option value="ascending">Sort in ascending order</option>
133+
</select>
134+
</div>
135+
<div class="vp-grid-box">
136+
<label class="vp-bold">Sort condition</label>
137+
<input type="text" id="sortHue" class="vp-input vp-state" placeholder="Type hue condition"/>
138+
<label><input type="checkbox" id="sortHueText" class="vp-state"/><span>Text</span></label>
139+
</div>
140+
</div>
121141
</div>
122142
<label for="userOption" class="vp-bold">User Option</label>
123143
<input type="text" id="userOption" class="vp-input vp-state wp100" placeholder="key=value, ..."/>

js/m_visualize/Seaborn.js

Lines changed: 131 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ define([
5050
stat: '',
5151
showValues: false,
5252
showValuesPrecision: '',
53+
sortBy: 'y',
54+
sortType: '',
55+
sortHue: '',
56+
sortHueText: false,
5357
// axes options
5458
x_limit_from: '',
5559
x_limit_to: '',
@@ -194,8 +198,10 @@ define([
194198
$(that.wrapSelector('#stat')).closest('.sb-option').show();
195199
} else if (chartType == 'barplot') {
196200
$(that.wrapSelector('#showValues')).closest('.sb-option').show();
201+
$(that.wrapSelector('#sortBy')).closest('.sb-option').show();
197202
} else if (chartType == 'countplot') {
198203
$(that.wrapSelector('#showValues')).closest('.sb-option').show();
204+
$(that.wrapSelector('#sortBy')).closest('.sb-option').show();
199205
}
200206
});
201207

@@ -209,6 +215,11 @@ define([
209215
$(that.wrapSelector('#x')).closest('.vp-ds-box').replaceWith('<select id="x"></select>');
210216
$(that.wrapSelector('#y')).closest('.vp-ds-box').replaceWith('<select id="y"></select>');
211217
$(that.wrapSelector('#hue')).closest('.vp-ds-box').replaceWith('<select id="hue"></select>');
218+
219+
// FIXME: hide sort values for barplot/countplot (as temporary)
220+
if (that.state.chartType == 'barplot' || that.state.chartType == 'countplot') {
221+
$(that.wrapSelector('#sortBy')).closest('.sb-option').show();
222+
}
212223
} else {
213224
// set X Y indivisually
214225
// disable data selection
@@ -227,10 +238,43 @@ define([
227238

228239
let dataSelectorHue = new DataSelector({ pageThis: that, id: 'hue' });
229240
$(that.wrapSelector('#hue')).replaceWith(dataSelectorHue.toTagString());
241+
242+
// FIXME: hide sort values for barplot/countplot (as temporary)
243+
if (that.state.chartType == 'barplot' || that.state.chartType == 'countplot') {
244+
$(that.wrapSelector('#sortBy')).closest('.sb-option').hide();
245+
}
230246

231247
}
232248
});
233249

250+
// change hue
251+
$(document).off('change', this.wrapSelector('.vp-state'));
252+
$(document).on('change', this.wrapSelector('#hue'), function() {
253+
let { chartType, data } = that.state;
254+
let hue = $(this).val();
255+
if (chartType == 'barplot' || chartType == 'countplot') {
256+
let colDtype = $(that.wrapSelector('#hue')).find('option:selected').data('type');
257+
console.log(data, hue);
258+
// get result and load column list
259+
vpKernel.getColumnCategory(data, hue).then(function (resultObj) {
260+
let { result } = resultObj;
261+
try {
262+
var category = JSON.parse(result);
263+
if (category && category.length > 0 && colDtype == 'object') {
264+
// if it's categorical column and its dtype is object, check 'Text' as default
265+
$(that.wrapSelector('#sortHueText')).prop('checked', true);
266+
} else {
267+
$(that.wrapSelector('#sortHueText')).prop('checked', false);
268+
}
269+
$(that.wrapSelector('#sortHue')).replaceWith(that.templateForHueCondition(category, colDtype));
270+
} catch {
271+
$(that.wrapSelector('#sortHueText')).prop('checked', false);
272+
$(that.wrapSelector('#sortHue')).replaceWith(that.templateForHueCondition([], colDtype));
273+
}
274+
});
275+
}
276+
});
277+
234278
// use color or not
235279
$(this.wrapSelector('#useColor')).on('change', function() {
236280
that.state.useColor = $(this).prop('checked');
@@ -541,6 +585,25 @@ define([
541585
this.loadPreview();
542586
}
543587

588+
templateForHueCondition(category, dtype='object') {
589+
var vpCondSuggest = new SuggestInput();
590+
vpCondSuggest.setComponentID('sortHue');
591+
vpCondSuggest.addClass('vp-input vp-state');
592+
vpCondSuggest.setPlaceholder('Type hue condition');
593+
if (category && category.length > 0) {
594+
vpCondSuggest.setPlaceholder((dtype=='object'?'Categorical':dtype) + " dtype");
595+
vpCondSuggest.setSuggestList(function () { return category; });
596+
vpCondSuggest.setSelectEvent(function (value) {
597+
$(this.wrapSelector()).val(value);
598+
$(this.wrapSelector()).trigger('change');
599+
});
600+
vpCondSuggest.setNormalFilter(false);
601+
} else {
602+
vpCondSuggest.setPlaceholder(dtype==''?'Value':(dtype + " dtype"));
603+
}
604+
return vpCondSuggest.toTagString();
605+
}
606+
544607
bindSettingBox() {
545608
//====================================================================
546609
// Stylesheet suggestinput
@@ -706,7 +769,9 @@ define([
706769

707770
generateCode(preview=false) {
708771
let {
709-
chartType, data, x, y, setXY, hue, kde, stat, showValues, showValuesPrecision,
772+
chartType, data, x, y, setXY, hue, kde, stat,
773+
showValues, showValuesPrecision,
774+
sortType, sortBy, sortHue, sortHueText,
710775
userOption='',
711776
x_limit_from, x_limit_to, y_limit_from, y_limit_to,
712777
xticks, xticks_label, xticks_rotate, removeXticks,
@@ -722,25 +787,6 @@ define([
722787
let config = this.chartConfig[chartType];
723788
let state = JSON.parse(JSON.stringify(this.state));
724789

725-
let chartCode = new com_String();
726-
727-
let etcOptionCode = []
728-
if (useColor == true && color != '') {
729-
etcOptionCode.push(com_util.formatString("color='{0}'", color));
730-
}
731-
if (markerStyle != '') {
732-
// TODO: marker to seaborn argument (ex. marker='+' / markers={'Lunch':'s', 'Dinner':'X'})
733-
etcOptionCode.push(com_util.formatString("marker='{0}'", markerStyle));
734-
}
735-
if (showValues === true && chartType === 'barplot') {
736-
etcOptionCode.push('ci=None');
737-
}
738-
739-
// add user option
740-
if (userOption != '') {
741-
etcOptionCode.push(userOption);
742-
}
743-
744790
if (preview && useSampling) {
745791
// data sampling code for preview
746792
// convertedData = data + '.sample(n=' + sampleCount + ', random_state=0)';
@@ -762,7 +808,71 @@ define([
762808
state.data = com_util.formatString('_vp_sample({0}, {1})', data, sampleCount);
763809
}
764810
}
765-
}
811+
}
812+
813+
let chartCode = new com_String();
814+
815+
let etcOptionCode = []
816+
if (useColor == true && color != '') {
817+
etcOptionCode.push(com_util.formatString("color='{0}'", color));
818+
}
819+
if (markerStyle != '') {
820+
// TODO: marker to seaborn argument (ex. marker='+' / markers={'Lunch':'s', 'Dinner':'X'})
821+
etcOptionCode.push(com_util.formatString("marker='{0}'", markerStyle));
822+
}
823+
if (showValues === true && chartType === 'barplot') {
824+
etcOptionCode.push('ci=None');
825+
}
826+
if (sortType != '') {
827+
let sortCode = '';
828+
let sortTypeStr = (sortType === 'descending'? 'ascending=False': 'ascending=True');
829+
let sortX = state.x;
830+
let sortY = state.y;
831+
if (sortBy === 'x') {
832+
sortX = state.y;
833+
sortY = state.x;
834+
}
835+
if (chartType === 'barplot') {
836+
if (setXY === true) {
837+
// TODO: sort on setXY
838+
// if (hue !== '' && sortHue !== '') {
839+
// sortCode = com_util.formatString("{}.groupby({})[{}].mean().sort_values({}).index")
840+
// } else {
841+
// sortCode = com_util.formatString("pd.concat([{0},{1}], axis=1).groupby({2})[{3}].mean().sort_values({4}).index"
842+
// , sortX, sortY, sortX)
843+
// }
844+
} else {
845+
if (hue !== '' && sortHue !== '') {
846+
sortCode = com_util.formatString("{0}[{1}[{2}]=={3}].groupby({4})[{5}].mean().sort_values({6}).index"
847+
, state.data, state.data, state.hue, com_util.convertToStr(sortHue, sortHueText), sortX, sortY, sortTypeStr);
848+
} else {
849+
sortCode = com_util.formatString("{0}.groupby({1})[{2}].mean().sort_values({3}).index", state.data, sortX, sortY, sortTypeStr);
850+
}
851+
}
852+
} else if (chartType === 'countplot') {
853+
let countVar = sortX === ''? sortY: sortX;
854+
if (setXY === true) {
855+
// TODO: sort on setXY
856+
;
857+
} else {
858+
if (hue !== '' && sortHue !== '') {
859+
sortCode = com_util.formatString("{0}[{1}[{2}]=={3}][{4}].value_counts({5}).index"
860+
, state.data, state.data, state.hue, com_util.convertToStr(sortHue, sortHueText), countVar, sortTypeStr);
861+
} else {
862+
sortCode = com_util.formatString("{0}[{1}].value_counts({2}).index", state.data, countVar, sortTypeStr);
863+
}
864+
}
865+
}
866+
867+
if (sortCode != '') {
868+
etcOptionCode.push('order=' + sortCode);
869+
}
870+
}
871+
872+
// add user option
873+
if (userOption != '') {
874+
etcOptionCode.push(userOption);
875+
}
766876

767877
let generatedCode = com_generator.vp_codeGenerator(this, config, state
768878
, etcOptionCode.length > 0? ', ' + etcOptionCode.join(', '): '');

python/variableCommand.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ def _vp_sample(data, sample_cnt):
8484
sample_cnt = len(data) if len(data) < sample_cnt else sample_cnt
8585

8686
if dataType == 'DataFrame':
87-
return data.sample(sample_cnt)
87+
return data.sample(sample_cnt, random_state=0)
8888
elif dataType == 'Series':
89-
return data.sample(sample_cnt)
89+
return data.sample(sample_cnt, random_state=0)
9090
elif dataType == 'ndarray':
9191
return data[_vp_np.random.choice(data.shape[0], sample_cnt, replace=False)]
9292
elif dataType == 'list':

0 commit comments

Comments
 (0)