@@ -648,33 +648,125 @@ define([
648
648
$ ( document ) . off ( 'change' , this . wrapSelector ( '.vp-inner-popup-var2' ) ) ;
649
649
}
650
650
651
- bindEventForPopupPage ( ) {
651
+ bindEventForPopupPage ( menuType ) {
652
652
var that = this ;
653
- ///// add page
654
- // 1. add type
655
- $ ( this . wrapSelector ( '.vp-inner-popup-addtype' ) ) . on ( 'change' , function ( ) {
656
- var tab = $ ( this ) . val ( ) ;
657
- $ ( that . wrapSelector ( '.vp-inner-popup-tab' ) ) . hide ( ) ;
658
- $ ( that . wrapSelector ( '.vp-inner-popup-tab.' + tab ) ) . show ( ) ;
659
- } ) ;
660
-
661
- // 2-1. hide column selection box
662
- $ ( this . wrapSelector ( '.vp-inner-popup-var1box .vp-vs-data-type' ) ) . on ( 'change' , function ( ) {
663
- var type = $ ( this ) . val ( ) ;
664
- if ( type == 'DataFrame' ) {
665
- $ ( that . wrapSelector ( '.vp-inner-popup-var1col' ) ) . show ( ) ;
666
- } else {
667
- $ ( that . wrapSelector ( '.vp-inner-popup-var1col' ) ) . hide ( ) ;
668
- }
669
- } ) ;
670
-
671
- $ ( this . wrapSelector ( '.vp-inner-popup-var2box .vp-vs-data-type' ) ) . on ( 'change' , function ( ) {
672
- var type = $ ( this ) . val ( ) ;
673
- if ( type == 'DataFrame' ) {
674
- $ ( that . wrapSelector ( '.vp-inner-popup-var2col' ) ) . show ( ) ;
675
- } else {
676
- $ ( that . wrapSelector ( '.vp-inner-popup-var2col' ) ) . hide ( ) ;
677
- }
653
+
654
+ if ( menuType === FRAME_EDIT_TYPE . ADD_COL
655
+ || menuType === FRAME_EDIT_TYPE . ADD_ROW
656
+ || menuType === FRAME_EDIT_TYPE . REPLACE ) {
657
+ ///// add page
658
+ // 1. add type
659
+ $ ( this . wrapSelector ( '.vp-inner-popup-addtype' ) ) . on ( 'change' , function ( ) {
660
+ var tab = $ ( this ) . val ( ) ;
661
+ $ ( that . wrapSelector ( '.vp-inner-popup-tab' ) ) . hide ( ) ;
662
+ $ ( that . wrapSelector ( '.vp-inner-popup-tab.' + tab ) ) . show ( ) ;
663
+ } ) ;
664
+
665
+ // 2-1. hide column selection box
666
+ $ ( this . wrapSelector ( '.vp-inner-popup-var1box .vp-vs-data-type' ) ) . on ( 'change' , function ( ) {
667
+ var type = $ ( this ) . val ( ) ;
668
+ if ( type == 'DataFrame' ) {
669
+ $ ( that . wrapSelector ( '.vp-inner-popup-var1col' ) ) . show ( ) ;
670
+ } else {
671
+ $ ( that . wrapSelector ( '.vp-inner-popup-var1col' ) ) . hide ( ) ;
672
+ }
673
+ } ) ;
674
+
675
+ $ ( this . wrapSelector ( '.vp-inner-popup-var2box .vp-vs-data-type' ) ) . on ( 'change' , function ( ) {
676
+ var type = $ ( this ) . val ( ) ;
677
+ if ( type == 'DataFrame' ) {
678
+ $ ( that . wrapSelector ( '.vp-inner-popup-var2col' ) ) . show ( ) ;
679
+ } else {
680
+ $ ( that . wrapSelector ( '.vp-inner-popup-var2col' ) ) . hide ( ) ;
681
+ }
682
+ } ) ;
683
+ } else if ( menuType === FRAME_EDIT_TYPE . DISCRETIZE ) {
684
+ // change bins
685
+ $ ( this . wrapSelector ( '.vp-inner-popup-bins' ) ) . on ( 'change' , function ( ) {
686
+ let binsCount = $ ( this ) . val ( ) ;
687
+ that . handleDiscretizeEdges ( binsCount ) ;
688
+ } ) ;
689
+
690
+ // change cut to qcut(quantile based discretization)
691
+ $ ( this . wrapSelector ( '.vp-inner-popup-qcut' ) ) . on ( 'change' , function ( ) {
692
+ let qcut = $ ( this ) . prop ( 'checked' ) ;
693
+ // disable right and range table
694
+ if ( qcut === true ) {
695
+ $ ( that . wrapSelector ( '.vp-inner-popup-right' ) ) . prop ( 'disabled' , true ) ;
696
+ $ ( that . wrapSelector ( '.vp-inner-popup-range-table input:not(.vp-inner-popup-label):disabled' ) ) . addClass ( 'already-disabled' ) ;
697
+ $ ( that . wrapSelector ( '.vp-inner-popup-range-table input:not(.vp-inner-popup-label)' ) ) . prop ( 'disabled' , true ) ;
698
+ } else {
699
+ $ ( that . wrapSelector ( '.vp-inner-popup-right' ) ) . prop ( 'disabled' , false ) ;
700
+ $ ( that . wrapSelector ( '.vp-inner-popup-range-table input:not(.vp-inner-popup-label):not(.already-disabled)' ) ) . prop ( 'disabled' , false ) ;
701
+ $ ( that . wrapSelector ( '.vp-inner-popup-range-table input:not(.vp-inner-popup-label).already-disabled' ) ) . removeClass ( 'already-disabled' ) ;
702
+ }
703
+ } ) ;
704
+
705
+ // change right option
706
+ $ ( this . wrapSelector ( '.vp-inner-popup-right' ) ) . on ( 'change' , function ( ) {
707
+ let binsCount = $ ( that . wrapSelector ( '.vp-inner-popup-bins' ) ) . val ( ) ;
708
+ let right = $ ( this ) . prop ( 'checked' ) ;
709
+ that . handleDiscretizeEdges ( binsCount , right ) ;
710
+ } ) ;
711
+ }
712
+
713
+ }
714
+
715
+ handleDiscretizeEdges ( binsCount = 1 , right = true ) {
716
+ let that = this ;
717
+ $ ( this . wrapSelector ( '.vp-inner-popup-range-table tbody' ) ) . html ( '' ) ;
718
+ $ ( this . wrapSelector ( '.vp-inner-popup-islabelchanged' ) ) . val ( "false" ) ;
719
+ $ ( that . wrapSelector ( '.vp-inner-popup-isedgechanged' ) ) . val ( "false" ) ;
720
+
721
+ let code = new com_String ( ) ;
722
+ code . appendFormatLine ( "_out, _bins = pd.cut({0}[{1}], bins={2}, right={3}, retbins=True)"
723
+ , this . state . tempObj , this . state . selected [ 0 ] . code , binsCount , right ?'True' :'False' ) ;
724
+ code . append ( "_vp_print({'labels': [str(o) for o in _out.cat.categories], 'edges': list(_bins)})" ) ;
725
+ vpKernel . execute ( code . toString ( ) ) . then ( function ( resultObj ) {
726
+ let { result } = resultObj ;
727
+ let { labels, edges } = JSON . parse ( result ) ;
728
+
729
+ let edgeTbody = new com_String ( ) ;
730
+ labels && labels . forEach ( ( label , idx ) => {
731
+ let leftDisabled = 'disabled' ;
732
+ let rightDisabled = '' ;
733
+ if ( idx === ( labels . length - 1 ) ) {
734
+ rightDisabled = 'disabled' ;
735
+ }
736
+ if ( right === false ) {
737
+ [ leftDisabled , rightDisabled ] = [ rightDisabled , leftDisabled ] ;
738
+ }
739
+ edgeTbody . append ( '<tr>' ) ;
740
+ edgeTbody . appendFormatLine ( '<td><input type="text" class="vp-input m vp-inner-popup-label" data-idx="{0}" value="{1}"/></td>' , idx , label ) ;
741
+ edgeTbody . appendLine ( '<td>:</td>' ) ;
742
+ edgeTbody . appendFormatLine ( '<td><input type="number" class="vp-input m vp-inner-popup-left-edge" data-idx="{0}" value="{1}" {2}/></td>' , idx , edges [ idx ] , leftDisabled ) ;
743
+ edgeTbody . appendLine ( '<td>~</td>' ) ;
744
+ edgeTbody . appendFormatLine ( '<td><input type="number" class="vp-input m vp-inner-popup-right-edge" data-idx="{0}" value="{1}" {2}/></td>' , idx + 1 , edges [ idx + 1 ] , rightDisabled ) ;
745
+ edgeTbody . append ( '</tr>' ) ;
746
+ } ) ;
747
+ $ ( that . wrapSelector ( '.vp-inner-popup-range-table tbody' ) ) . html ( edgeTbody . toString ( ) ) ;
748
+
749
+ // label change event
750
+ $ ( that . wrapSelector ( '.vp-inner-popup-label' ) ) . change ( function ( ) {
751
+ $ ( that . wrapSelector ( '.vp-inner-popup-islabelchanged' ) ) . val ( "true" ) ;
752
+ } ) ;
753
+
754
+ // edge change event
755
+ $ ( that . wrapSelector ( '.vp-inner-popup-left-edge' ) ) . change ( function ( ) {
756
+ let idx = $ ( this ) . data ( 'idx' ) ;
757
+ let val = $ ( this ) . val ( ) ;
758
+ $ ( that . wrapSelector ( `.vp-inner-popup-right-edge[data-idx=${ idx } ]` ) ) . val ( val ) ;
759
+ $ ( that . wrapSelector ( '.vp-inner-popup-isedgechanged' ) ) . val ( "true" ) ;
760
+ } ) ;
761
+ $ ( that . wrapSelector ( '.vp-inner-popup-right-edge' ) ) . change ( function ( ) {
762
+ let idx = $ ( this ) . data ( 'idx' ) ;
763
+ let val = $ ( this ) . val ( ) ;
764
+ $ ( that . wrapSelector ( `.vp-inner-popup-left-edge[data-idx=${ idx } ]` ) ) . val ( val ) ;
765
+ $ ( that . wrapSelector ( '.vp-inner-popup-isedgechanged' ) ) . val ( "true" ) ;
766
+ } ) ;
767
+
768
+ } ) . catch ( function ( errObj ) {
769
+ // TODO:
678
770
} ) ;
679
771
}
680
772
@@ -1014,6 +1106,53 @@ define([
1014
1106
return content . toString ( ) ;
1015
1107
}
1016
1108
1109
+ renderDiscretizePage ( ) {
1110
+ var content = new com_String ( ) ;
1111
+ content . appendLine ( `
1112
+ <div class="vp-inner-popup-discretize-page vp-grid-box">
1113
+ <div class="vp-grid-col-110">
1114
+ <label class="vp-orange-text">Column name</label>
1115
+ <input type="text" class="vp-input" value="${ this . state . selected [ 0 ] . label } " disabled />
1116
+ <label>Bins count</label>
1117
+ <input type="number" class="vp-input vp-inner-popup-bins" placeholder="Input count of bins"/>
1118
+ </div>
1119
+ <label title="pd.qcut() option">
1120
+ <input type="checkbox" class="vp-inner-popup-qcut">
1121
+ <span>Quantile-based discretization</span>
1122
+ </label>
1123
+ <label title="right option">
1124
+ <input type="checkbox" class="vp-inner-popup-right" checked>
1125
+ <span>Include the rightmost edge</span>
1126
+ </label>
1127
+ <hr style="margin: 5px 0;"/>
1128
+ <table class="vp-tbl-gap5 vp-inner-popup-range-table">
1129
+ <colgroup><col width="116px"><col width="5px"><col width="116px"><col width="5px"><col width="*"></colgroup>
1130
+ <thead>
1131
+ <tr>
1132
+ <th>Label</th>
1133
+ <th></th>
1134
+ <th>Left edge</th>
1135
+ <th></th>
1136
+ <th>Right edge</th>
1137
+ </tr>
1138
+ </thead>
1139
+ <tbody>
1140
+ </tbody>
1141
+ </table>
1142
+ <label title="Set all labels as text">
1143
+ <input type="checkbox" class="vp-inner-popup-labelastext" checked>
1144
+ <span>Label as Text</span>
1145
+ </label>
1146
+ <input type="hidden" class="vp-inner-popup-islabelchanged" value=false />
1147
+ <input type="hidden" class="vp-inner-popup-isedgechanged" value=false />
1148
+ </div>
1149
+ ` )
1150
+
1151
+ // set content
1152
+ $ ( this . wrapSelector ( '.vp-inner-popup-body' ) ) . html ( content . toString ( ) ) ;
1153
+ return content . toString ( ) ;
1154
+ }
1155
+
1017
1156
renderSortPage ( ) {
1018
1157
var content = new com_String ( ) ;
1019
1158
content . appendFormatLine ( '<div class="{0}">' , 'vp-inner-popup-sort-page' ) ;
@@ -1152,6 +1291,16 @@ define([
1152
1291
title = 'Rename' ;
1153
1292
content = this . renderRenamePage ( ) ;
1154
1293
break ;
1294
+ case FRAME_EDIT_TYPE . DISCRETIZE :
1295
+ title = 'Discretize' ;
1296
+ size = { width : 450 , height : 450 } ;
1297
+ content = this . renderDiscretizePage ( ) ;
1298
+ break ;
1299
+ case FRAME_EDIT_TYPE . DATA_SHIFT :
1300
+ title = 'Data shift' ;
1301
+ // TODO:
1302
+ content = 'WIP' ;
1303
+ break ;
1155
1304
case FRAME_EDIT_TYPE . SORT_INDEX :
1156
1305
title = 'Sort by index' ;
1157
1306
content = this . renderSortPage ( ) ;
@@ -1206,6 +1355,11 @@ define([
1206
1355
title = 'Convert type' ;
1207
1356
content = this . renderAsType ( ) ;
1208
1357
break ;
1358
+ case FRAME_EDIT_TYPE . FILL_NA :
1359
+ title = 'Fill NA' ;
1360
+ // TODO:
1361
+ content = 'WIP' ;
1362
+ break ;
1209
1363
default :
1210
1364
type = FRAME_EDIT_TYPE . NONE ;
1211
1365
break ;
@@ -1217,7 +1371,7 @@ define([
1217
1371
$ ( this . wrapSelector ( '.vp-inner-popup-box' ) ) . css ( size ) ;
1218
1372
1219
1373
// bindEventForAddPage
1220
- this . bindEventForPopupPage ( ) ;
1374
+ this . bindEventForPopupPage ( type ) ;
1221
1375
1222
1376
// set column list
1223
1377
vpKernel . getColumnList ( this . state . tempObj ) . then ( function ( resultObj ) {
@@ -1344,6 +1498,30 @@ define([
1344
1498
} ;
1345
1499
} ) ;
1346
1500
break ;
1501
+ case FRAME_EDIT_TYPE . DISCRETIZE :
1502
+ content [ 'bins' ] = $ ( this . wrapSelector ( '.vp-inner-popup-bins' ) ) . val ( ) ;
1503
+ content [ 'isqcut' ] = $ ( this . wrapSelector ( '.vp-inner-popup-qcut' ) ) . prop ( 'checked' ) ;
1504
+ content [ 'isright' ] = $ ( this . wrapSelector ( '.vp-inner-popup-right' ) ) . prop ( 'checked' ) ;
1505
+ let labelastext = $ ( this . wrapSelector ( '.vp-inner-popup-labelastext' ) ) . prop ( 'checked' ) ;
1506
+ let islabelchanged = $ ( this . wrapSelector ( '.vp-inner-popup-islabelchanged' ) ) . val ( ) === 'true' ;
1507
+ let isedgechanged = $ ( this . wrapSelector ( '.vp-inner-popup-isedgechanged' ) ) . val ( ) === 'true' ;
1508
+ let rangeTableTags = $ ( this . wrapSelector ( '.vp-inner-popup-range-table tbody tr' ) ) ;
1509
+ let labels = [ ] ;
1510
+ let edges = [ ] ;
1511
+ rangeTableTags && rangeTableTags . each ( ( idx , tag ) => {
1512
+ if ( islabelchanged === true ) {
1513
+ labels . push ( com_util . convertToStr ( $ ( tag ) . find ( '.vp-inner-popup-label' ) . val ( ) , labelastext ) ) ;
1514
+ }
1515
+ if ( content [ 'isqcut' ] === false && isedgechanged === true ) {
1516
+ edges . push ( $ ( tag ) . find ( '.vp-inner-popup-left-edge' ) . val ( ) ) ;
1517
+ if ( idx === ( rangeTableTags . length - 1 ) ) {
1518
+ edges . push ( $ ( tag ) . find ( '.vp-inner-popup-right-edge' ) . val ( ) ) ;
1519
+ }
1520
+ }
1521
+ } ) ;
1522
+ content [ 'labels' ] = labels ;
1523
+ content [ 'edges' ] = edges ;
1524
+ break ;
1347
1525
default :
1348
1526
break ;
1349
1527
}
@@ -1601,6 +1779,28 @@ define([
1601
1779
} ) ;
1602
1780
code . appendFormat ( "{0} = {1}.astype({{2}})" , tempObj , tempObj , astypeStr . toString ( ) ) ;
1603
1781
break ;
1782
+ case FRAME_EDIT_TYPE . DISCRETIZE :
1783
+ let method = 'cut' ;
1784
+ let bins = content [ 'bins' ] ;
1785
+ if ( content [ 'isqcut' ] === true ) {
1786
+ method = 'qcut' ;
1787
+ } else {
1788
+ if ( content [ 'isedgechanged' ] === true ) {
1789
+ bins = "[" + content [ 'edges' ] . join ( ',' ) + "]" ;
1790
+ }
1791
+ }
1792
+
1793
+ code . appendFormat ( "{0}[{1}] = pd.{2}({3}[{4}], {5}"
1794
+ , tempObj , selectedName , method , tempObj , selectedName , bins ) ;
1795
+
1796
+ if ( method === 'cut' && content [ 'isright' ] === false ) {
1797
+ code . append ( ", right=False" ) ;
1798
+ }
1799
+ if ( content [ 'labels' ] && content [ 'labels' ] . length > 0 ) {
1800
+ code . appendFormat ( ", labels=[{0}]" , content [ 'labels' ] . join ( ', ' ) ) ;
1801
+ }
1802
+ code . append ( ')' ) ;
1803
+ break ;
1604
1804
case FRAME_EDIT_TYPE . SHOW :
1605
1805
break ;
1606
1806
}
0 commit comments