From cfbc858f8f60a7ecd0ad42ee91854cb66b117c58 Mon Sep 17 00:00:00 2001 From: Minku Koo Date: Wed, 31 Jan 2024 21:06:17 +0900 Subject: [PATCH 01/12] Fixed #256 : [BUG] Scrolling Issue with iloc in Subset App When iloc is selected in Subset app - Fixes incorrect indexing issue - Resolves scrollbar being fixed downwards, preventing number clicking and scrolling up. --- visualpython/js/m_apps/Subset.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/visualpython/js/m_apps/Subset.js b/visualpython/js/m_apps/Subset.js index 7c7c74c8..4fdbb2c0 100644 --- a/visualpython/js/m_apps/Subset.js +++ b/visualpython/js/m_apps/Subset.js @@ -343,6 +343,9 @@ define([ $(this.wrapSelector('.select-row .vp-ds-select-box.left')).on('scroll', function() { if ($(this).scrollTop() + $(this).innerHeight() >= ($(this)[0].scrollHeight - 2)) { let scrollPos = $(this).scrollTop(); + if (that.state.rowLimit > that.state.rowList.length){ + return; // Prevents scroll from being fixed downwards + } let start = that.state.rowLimit; let end = start + 10; let subsetVariable = com_util.formatString('{0}.iloc[{1}:{2}]', that.state.pandasObject, start, end); @@ -361,9 +364,9 @@ define([ rowList = rowList.map(function (x) { return { ...x, - label: x.location + '', - value: x.location + '', - code: x.location + '', + label: x.label + '', + value: x.value + '', + code: x.code + '', }; }); } From e7565a12701eef53e38d524c8b41ff1bd9e0f2fc Mon Sep 17 00:00:00 2001 From: Minku Koo Date: Fri, 1 Mar 2024 23:32:32 +0900 Subject: [PATCH 02/12] Fixed #258 : Incorrect Behavior of 'Add All' and 'Del All' Buttons in Subset App Ensure Proper Sorting of Items after 'Del All' Operation --- visualpython/js/com/com_Kernel.js | 8 ++++++-- visualpython/js/m_apps/Subset.js | 2 +- visualpython/python/pandasCommand.py | 5 +++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/visualpython/js/com/com_Kernel.js b/visualpython/js/com/com_Kernel.js index 3540d1f0..addb7093 100644 --- a/visualpython/js/com/com_Kernel.js +++ b/visualpython/js/com/com_Kernel.js @@ -610,10 +610,14 @@ define([ * @param {*} dataframe * @returns */ - getRowList(dataframe) { + getRowList(dataframe, start_idx) { var that = this; + if (typeof start_idx === 'undefined') { + start_idx = 0; + } + return new Promise(function(resolve, reject) { - that.execute(com_util.formatString('_vp_print(_vp_get_rows_list({0}))', dataframe)) + that.execute(com_util.formatString('_vp_print(_vp_get_rows_list({0}, {1}))', dataframe, start_idx)) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { diff --git a/visualpython/js/m_apps/Subset.js b/visualpython/js/m_apps/Subset.js index 4fdbb2c0..41af3ef4 100644 --- a/visualpython/js/m_apps/Subset.js +++ b/visualpython/js/m_apps/Subset.js @@ -349,7 +349,7 @@ define([ let start = that.state.rowLimit; let end = start + 10; let subsetVariable = com_util.formatString('{0}.iloc[{1}:{2}]', that.state.pandasObject, start, end); - vpKernel.getRowList(subsetVariable).then(function (resultObj) { + vpKernel.getRowList(subsetVariable, start).then(function (resultObj) { let { result } = resultObj; var { list:rowList } = JSON.parse(result); rowList = rowList.map(function (x) { diff --git a/visualpython/python/pandasCommand.py b/visualpython/python/pandasCommand.py index aee1338d..4f8301c6 100644 --- a/visualpython/python/pandasCommand.py +++ b/visualpython/python/pandasCommand.py @@ -11,7 +11,7 @@ # from IPython.core.display is deprecated since IPython 7.14 from IPython.display import display -def _vp_get_rows_list(df): +def _vp_get_rows_list(df, start_idx=0): """ Get Rows List with Detail Information """ @@ -19,7 +19,8 @@ def _vp_get_rows_list(df): indexType = str(df.index.dtype) # make dict for rows info for i, r in enumerate(df.index): - rInfo = { 'label': r, 'value': r, 'location': i } + rInfo = { 'label': r, 'value': r, 'location': start_idx + i } + # value if type(r).__name__ == 'str': rInfo['value'] = "'{}'".format(r) From cde3b3ece38a7de84c78ece949f12094b470aa00 Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Tue, 7 May 2024 13:41:53 +0900 Subject: [PATCH 03/12] Fix typo - class-fication to class-i-fication --- visualpython/js/m_ml/Classification.js | 2 +- visualpython/js/m_ml/Clustering.js | 2 +- visualpython/js/m_ml/GridSearch.js | 2 +- visualpython/js/m_ml/evaluation.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/visualpython/js/m_ml/Classification.js b/visualpython/js/m_ml/Classification.js index f487be39..f327b611 100644 --- a/visualpython/js/m_ml/Classification.js +++ b/visualpython/js/m_ml/Classification.js @@ -50,7 +50,7 @@ define([ this.modelConfig = ML_LIBRARIES; this.modelTypeList = { - 'Classfication': ['lg-rgs', 'bern-nb', 'mulnom-nb', 'gaus-nb', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], + 'Classification': ['lg-rgs', 'bern-nb', 'mulnom-nb', 'gaus-nb', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], } diff --git a/visualpython/js/m_ml/Clustering.js b/visualpython/js/m_ml/Clustering.js index c3781201..95ee735c 100644 --- a/visualpython/js/m_ml/Clustering.js +++ b/visualpython/js/m_ml/Clustering.js @@ -51,7 +51,7 @@ define([ this.modelTypeList = { // 'Regression': ['ln-rgs', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], - // 'Classfication': ['lg-rgs', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], + // 'Classification': ['lg-rgs', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'], // 'Auto ML': ['tpot-rgs', 'tpot-clf'], 'Clustering': ['k-means', 'agg-cls', 'gaus-mix', 'dbscan'], // 'Dimension Reduction': ['pca', 'lda', 'svd', 'nmf'] diff --git a/visualpython/js/m_ml/GridSearch.js b/visualpython/js/m_ml/GridSearch.js index 32dbc967..1dfdbaa4 100644 --- a/visualpython/js/m_ml/GridSearch.js +++ b/visualpython/js/m_ml/GridSearch.js @@ -49,7 +49,7 @@ define([ this.modelTypeList = { 'Regression': ['ln-rgs', 'ridge', 'lasso', 'elasticnet', 'sv-rgs', 'dt-rgs', 'rf-rgs', 'gbm-rgs', 'xgb-rgs', 'lgbm-rgs', 'cb-rgs'], - 'Classfication': ['lg-rgs', 'bern-nb', 'mulnom-nb', 'gaus-nb', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'] + 'Classification': ['lg-rgs', 'bern-nb', 'mulnom-nb', 'gaus-nb', 'sv-clf', 'dt-clf', 'rf-clf', 'gbm-clf', 'xgb-clf', 'lgbm-clf', 'cb-clf'] } diff --git a/visualpython/js/m_ml/evaluation.js b/visualpython/js/m_ml/evaluation.js index 1cf1552d..d3c59514 100644 --- a/visualpython/js/m_ml/evaluation.js +++ b/visualpython/js/m_ml/evaluation.js @@ -204,7 +204,7 @@ define([ let needMarkdown = false; //==================================================================== - // Classfication + // Classification //==================================================================== if (modelType == 'clf') { if (confusion_matrix) { From bd1627a81332a51a8f36ae38b6a0474a9cec9483 Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Tue, 7 May 2024 13:47:06 +0900 Subject: [PATCH 04/12] Edit fillna to get first element of Series which mode() returns --- visualpython/js/m_apps/Frame.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/visualpython/js/m_apps/Frame.js b/visualpython/js/m_apps/Frame.js index fd786ad0..4e91083d 100644 --- a/visualpython/js/m_apps/Frame.js +++ b/visualpython/js/m_apps/Frame.js @@ -3620,7 +3620,12 @@ define([ code.appendFormat(", limit={0}", content['limit']); } } else { - code.appendFormat("{0}.{1}()", subsetObjStr, content['method']); + if (content['method'] === 'mode') { + // get mode()'s first element (mode returns Series) + code.appendFormat("{0}.{1}()[0]", subsetObjStr, content['method']); + } else { + code.appendFormat("{0}.{1}()", subsetObjStr, content['method']); + } } code.append(')'); break; From 7c0635c8e62d718f2eb5ca1e0616c9da0ce0c276 Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Tue, 7 May 2024 13:51:32 +0900 Subject: [PATCH 05/12] Edit DataPrep > OneHotEncoder option from sparse to sparse_output, set default selected value to False --- visualpython/data/m_ml/mlLibrary.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/visualpython/data/m_ml/mlLibrary.js b/visualpython/data/m_ml/mlLibrary.js index 5f574e33..413587b1 100644 --- a/visualpython/data/m_ml/mlLibrary.js +++ b/visualpython/data/m_ml/mlLibrary.js @@ -128,10 +128,10 @@ define([ 'prep-onehot': { name: 'OneHotEncoder', import: 'from sklearn.preprocessing import OneHotEncoder', - code: 'OneHotEncoder(${sparse}${handle_unknown}${etc})', + code: 'OneHotEncoder(${sparse_output}${handle_unknown}${etc})', returnType: 'OneHotEncoder', options: [ - { name: 'sparse', component: ['bool_select'], default: 'False', usePair: true }, + { name: 'sparse_output', component: ['bool_select'], default: 'True', value: 'False', usePair: true }, { name: 'handle_unknown', component: ['option_suggest'], usePair: true, options: ['error', 'ignore'], default: 'error' }, ] From f1ebe042c8ed6a15bf622b66e8705112d710eed4 Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Mon, 13 May 2024 15:23:27 +0900 Subject: [PATCH 06/12] Fixed typo --- visualpython/data/m_library/pandasLibrary.js | 6 +++--- visualpython/data/m_library/pandasLibrary_v1.js | 6 +++--- visualpython/js/m_apps/File.js | 6 +++--- visualpython/js/m_ml/evaluation.js | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/visualpython/data/m_library/pandasLibrary.js b/visualpython/data/m_library/pandasLibrary.js index 08ef7889..1478aa9e 100644 --- a/visualpython/data/m_library/pandasLibrary.js +++ b/visualpython/data/m_library/pandasLibrary.js @@ -206,7 +206,7 @@ define([ }, { "name": "sep", - "label": "Seperator", + "label": "Separator", "type": "text", "usePair": true }, @@ -304,7 +304,7 @@ define([ }, { "name": "sep", - "label": "Seperator", + "label": "Separator", "type": "text", "usePair": true }, @@ -4342,7 +4342,7 @@ define([ }, { "name": "prefix_sep", - "label": "Header Seperator", + "label": "Header Separator", "default": "_", "usePair": true }, diff --git a/visualpython/data/m_library/pandasLibrary_v1.js b/visualpython/data/m_library/pandasLibrary_v1.js index d1f38172..f97c6546 100644 --- a/visualpython/data/m_library/pandasLibrary_v1.js +++ b/visualpython/data/m_library/pandasLibrary_v1.js @@ -163,7 +163,7 @@ define([ { name: 'sep', type: 'text', - label: 'Seperator' + label: 'Separator' }, { name: 'names', @@ -243,7 +243,7 @@ define([ { name: 'sep', type: 'text', - label: 'Seperator' + label: 'Separator' }, { name: 'na_rep', @@ -3514,7 +3514,7 @@ define([ { name: 'prefix_sep', type: ['text'], - label: 'Header Seperator', + label: 'Header Separator', default: '_' }, { diff --git a/visualpython/js/m_apps/File.js b/visualpython/js/m_apps/File.js index 6a04a91c..2a3e8741 100644 --- a/visualpython/js/m_apps/File.js +++ b/visualpython/js/m_apps/File.js @@ -499,15 +499,15 @@ define([ return suggestInput.toTagString(); }); - // seperator suggest input + // separator suggest input $(this.wrapSelector('#sep')).replaceWith(function() { - // seperator list : + // separator list : var sepList = [',', '|', '\\t', '\\n', ':', ';', '-', '_', '&', '/', '\\']; var suggestInput = new SuggestInput(); suggestInput.setComponentID('sep'); suggestInput.addClass('vp-input vp-state'); suggestInput.setSuggestList(function() { return sepList; }); - suggestInput.setPlaceholder('Input seperator'); + suggestInput.setPlaceholder('Input separator'); return suggestInput.toTagString(); }); } diff --git a/visualpython/js/m_ml/evaluation.js b/visualpython/js/m_ml/evaluation.js index d3c59514..2484d623 100644 --- a/visualpython/js/m_ml/evaluation.js +++ b/visualpython/js/m_ml/evaluation.js @@ -351,7 +351,7 @@ define([ ...codeCells ]; } - // return as seperated cells + // return as separated cells return codeCells; } From 9fe0c6c0a9391605ec37d3e39a25b3de02100b24 Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Mon, 13 May 2024 15:46:09 +0900 Subject: [PATCH 07/12] Added RMSE for Statistics' Regression --- visualpython/html/m_stats/regression.html | 1 + visualpython/js/m_stats/Regression.js | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/visualpython/html/m_stats/regression.html b/visualpython/html/m_stats/regression.html index 124f7066..93ac63fd 100644 --- a/visualpython/html/m_stats/regression.html +++ b/visualpython/html/m_stats/regression.html @@ -76,6 +76,7 @@ + diff --git a/visualpython/js/m_stats/Regression.js b/visualpython/js/m_stats/Regression.js index 89b0738d..a38c811b 100644 --- a/visualpython/js/m_stats/Regression.js +++ b/visualpython/js/m_stats/Regression.js @@ -58,6 +58,7 @@ define([ normTest: true, histogram: true, scatterplot: true, + rmse: false, ...this.state }; @@ -259,7 +260,7 @@ define([ // Multi-collinearity multiCollinearity, // Residual option - statistics, normTest, histogram, scatterplot + statistics, normTest, histogram, scatterplot, rmse, } = this.state; let codeList = []; let code = new com_String(); @@ -697,7 +698,7 @@ define([ } // Residual option - if (statistics === true || normTest === true || histogram === true || scatterplot === true) { + if (statistics === true || normTest === true || histogram === true || scatterplot === true || rmse === true) { let residualTitle = 'Residual' if (lastModelNum > 0) { residualTitle += ' - Model ' + lastModelNum; @@ -768,6 +769,14 @@ define([ code.appendLine(" plt.tight_layout()"); code.append(" plt.show()"); } + if (rmse === true) { + code.appendLine(); + code.appendLine(); + code.appendLine("# RMSE (Root Mean Squared Error)"); + code.appendLine("_rmse = np.sqrt(_result.mse_resid)"); + code.appendLine("display(Markdown('### RMSE (Root Mean Squared Error)'))"); + code.append("display(Markdown(f'RMSE: {_rmse}'))"); + } } codeList.push(code.toString()); From 1215bdd7630ad1baf9fc577589af16ae13ec0a11 Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Mon, 13 May 2024 15:54:36 +0900 Subject: [PATCH 08/12] Fixed dt-clf criterion options --- visualpython/data/m_ml/mlLibrary.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/visualpython/data/m_ml/mlLibrary.js b/visualpython/data/m_ml/mlLibrary.js index 413587b1..11fc11a8 100644 --- a/visualpython/data/m_ml/mlLibrary.js +++ b/visualpython/data/m_ml/mlLibrary.js @@ -490,8 +490,8 @@ define([ code: 'DecisionTreeClassifier(${criterion}${max_depth}${min_samples_split}${random_state}${etc})', returnType: 'DecisionTreeClassifier', options: [ - { name: 'criterion', component: ['option_select'], type: 'text', default: 'squared_error', type:'text', - options: ['squared_error', 'friedman_mse', 'absolute_error', 'poisson'], usePair: true }, + { name: 'criterion', component: ['option_select'], type: 'text', default: 'gini', type:'text', + options: ['gini','entropy','log_loss'], usePair: true }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'min_samples_split', component: ['input_number'], default: 2, usePair: true }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } @@ -505,7 +505,7 @@ define([ options: [ { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, { name: 'criterion', component: ['option_select'], type: 'text', default: 'gini', type:'text', usePair: true, - options: ['gini', 'entropy'] }, + options: ['gini', 'entropy', 'log_loss'] }, { name: 'max_depth', component: ['input_number'], placeholder: 'None', usePair: true }, { name: 'min_samples_split', component: ['input_number'], default: 2, usePair: true }, { name: 'n_jobs', component: ['input_number'], placeholder: 'None', usePair: true }, @@ -518,12 +518,12 @@ define([ code: 'GradientBoostingClassifier(${loss}${learning_rate}${n_estimators}${criterion}${random_state}${etc})', returnType: 'GradientBoostingClassifier', options: [ - { name: 'loss', component: ['option_select'], type: 'text', default: 'deviance', type: 'text', usePair: true, - options: ['deviance', 'exponential'] }, + { name: 'loss', component: ['option_select'], type: 'text', default: 'log_loss', type: 'text', usePair: true, + options: ['log_loss', 'exponential'] }, { name: 'learning_rate', component: ['input_number'], default: 0.1, usePair: true }, { name: 'n_estimators', component: ['input_number'], default: 100, usePair: true }, { name: 'criterion', component: ['option_select'], type: 'text', default: 'friedman_mse', type:'text', usePair: true, - options: ['friedman_mse', 'squared_error', 'mse', 'mae'] }, + options: ['friedman_mse', 'squared_error'] }, { name: 'random_state', component: ['input_number'], placeholder: '123', usePair: true } ] }, From 9c752dd42c5935c5f28be5d35f5e1c9cc7272aba Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Mon, 13 May 2024 16:38:50 +0900 Subject: [PATCH 09/12] Fixed pipeline > gridsearch to apply evaluation model type --- visualpython/js/m_ml/Pipeline.js | 29 ++++++++++++++++++++++++++++- visualpython/js/m_ml/evaluation.js | 3 +++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/visualpython/js/m_ml/Pipeline.js b/visualpython/js/m_ml/Pipeline.js index 6dfc1989..856c33db 100644 --- a/visualpython/js/m_ml/Pipeline.js +++ b/visualpython/js/m_ml/Pipeline.js @@ -210,6 +210,7 @@ define([ $(that.wrapSelector(`.vp-pp-step-page:not([data-name="${name}"])`)).hide(); $(that.wrapSelector(`.vp-pp-step-page[data-name="${name}"]`)).show(); if (ppObj.useApp === true) { + ppObj.app && that.handleAppView(name, ppObj.app); ppObj.app && ppObj.app.open($(that.wrapSelector(`.vp-pp-step-page[data-name="${name}"]`))); } else { that.renderApp(name); @@ -372,7 +373,7 @@ define([ // click next button $(this.wrapSelector('.vp-pp-step-next:not(.disabled)')).on('click', function() { let selectedTag = $(that.wrapSelector('.vp-pp-item.selected')); - let nextTagList = $(selectedTag).nextAll('.vp-pp-item[data-flag="enabled"]:visible') + let nextTagList = $(selectedTag).nextAll('.vp-pp-item[data-flag="enabled"]:visible'); $(nextTagList[0]).trigger('click'); }); } @@ -562,6 +563,32 @@ define([ case 'ml_dataSplit': $(mlApp.wrapSelector('#inputData')).parent().hide(); break; + case 'ml_evaluation': + // for pipeline + $(mlApp.wrapSelector('.vp-upper-box')).hide(); + $(mlApp.wrapSelector('.vp-upper-box.' + mlApp.state.modelType)).show(); + + $(mlApp.wrapSelector('.vp-eval-box')).hide(); + $(mlApp.wrapSelector('.vp-eval-' + mlApp.state.modelType)).show(); + + if (mlApp.state.modelType == 'rgs') { + // Regression + + } else if (mlApp.state.modelType == 'clf') { + // Classification + // if (this.state.roc_curve == false && this.state.auc == false) { + // $(page).find('.vp-ev-model.roc-auc').prop('disabled', true); + // } + } else { + // Clustering + if (mlApp.state.silhouetteScore == false) { + $(mlApp.wrapSelector('.vp-ev-model.silhouette')).prop('disabled', true); + } + if (mlApp.state.ari == false && mlApp.state.nmi == false) { + $(mlApp.wrapSelector('.vp-ev-model.ari-nmi')).prop('disabled', true); + } + } + break; } } diff --git a/visualpython/js/m_ml/evaluation.js b/visualpython/js/m_ml/evaluation.js index 2484d623..ed63120c 100644 --- a/visualpython/js/m_ml/evaluation.js +++ b/visualpython/js/m_ml/evaluation.js @@ -158,6 +158,9 @@ define([ $(page).find('.vp-upper-box').hide(); $(page).find('.vp-upper-box.' + this.state.modelType).show(); + + $(page).find('.vp-eval-box').hide(); + $(page).find('.vp-eval-' + this.state.modelType).show(); if (this.state.modelType == 'rgs') { // Regression From bf8fab6ead7e12d003265742aab2b2bed886ccc9 Mon Sep 17 00:00:00 2001 From: minjk-bl Date: Tue, 14 May 2024 16:29:23 +0900 Subject: [PATCH 10/12] Added returnframetype to DataSelector and Applied it to DataPrep and Dimension Reduction --- visualpython/js/com/com_generatorV2.js | 8 +- visualpython/js/com/component/DataSelector.js | 154 +++++++++++++++--- visualpython/js/com/component/ModelEditor.js | 75 +++++++-- visualpython/js/m_ml/FitPredict.js | 102 ++++++++++-- 4 files changed, 283 insertions(+), 56 deletions(-) diff --git a/visualpython/js/com/com_generatorV2.js b/visualpython/js/com/com_generatorV2.js index f1762c36..42e6c760 100644 --- a/visualpython/js/com/com_generatorV2.js +++ b/visualpython/js/com/com_generatorV2.js @@ -376,6 +376,8 @@ define([ allowDataType: obj.var_type, placeholder: obj.placeholder || 'Select data', value: value, + columnSelection: obj.columnSelection || 'multiple', // single / multiple + returnFrameType: obj.returnFrameType || '', // '' / DataFrame / Series required: obj.required === true }); content = $(dataSelector.toTagString()); @@ -890,7 +892,7 @@ define([ suggestInputX.addClass('vp-input vp-state'); suggestInputX.setNormalFilter(false); suggestInputX.setValue(defaultValue); - $(selector + ' #' + columnInputId).replaceWith(function() { + $(pageThis.wrapSelector('#' + columnInputId)).replaceWith(function() { return suggestInputX.toTagString(); }); } else { @@ -899,7 +901,7 @@ define([ 'id': columnInputId, 'class': 'vp-select vp-state' }); - $(selector + ' #' + columnInputId).replaceWith(function() { + $(pageThis.wrapSelector('#' + columnInputId)).replaceWith(function() { return $(tag); }); } @@ -955,7 +957,7 @@ define([ suggestInputX.setSuggestList(function() { return list; }); //FIXME: suggestInputX.setNormalFilter(false); suggestInputX.setValue(defaultValue); - $(selector + ' #' + columnInputId).replaceWith(function() { + $(pageThis.wrapSelector('#' + columnInputId)).replaceWith(function() { return suggestInputX.toTagString(); }); } else { diff --git a/visualpython/js/com/component/DataSelector.js b/visualpython/js/com/component/DataSelector.js index 770770ba..1b64b9ee 100644 --- a/visualpython/js/com/component/DataSelector.js +++ b/visualpython/js/com/component/DataSelector.js @@ -59,6 +59,11 @@ define([ select: null, // callback after selection from suggestInput (value, dtype) allowDataType: null, // list of allowed data types dataCategory: null, // list of data category (use it for ml categories) + columnSelection: 'multiple', // single/multi : allowed column selection + returnFrameType: '', // DataFrame/Series : required data type for DataFrame -> Series/DataFrame operation + // if Series, only one column selection is allowed and returns Series + // if DataFrame, always returns DataFrame + // if Empty(=== ''), if one column selected, returns Series / others, returns DataFrame // additional options boxClasses: '', classes: '', @@ -87,6 +92,9 @@ define([ this.prop.dataCategory = this.prop.allowDataType; } } + if (this.prop.returnFrameType === 'Series') { + this.prop.columnSelection = 'single'; // only single selection allowed + } this.state = { filterType: 'All', @@ -98,6 +106,7 @@ define([ slicingEnd1: '', slicingStart2: '', slicingEnd2: '', + singleColumn: '', ndRowType: 'slicing', ndColType: 'slicing', useIndex: false, @@ -409,6 +418,19 @@ define([ } } + templateForSingleSelector() { + return ` +
+ +
+ + +
+
+ ` + } + templateForMultiSelector() { return `
@@ -599,22 +621,93 @@ define([ switch (dataType) { case 'DataFrame': - // render option page - $(this.wrapSelector('.vp-ds-option-inner-box')).html(this.templateForMultiSelector()); // column selecting - this._columnSelector = new MultiSelector(this.wrapSelector('.vp-ds-df-multiselector'), - { mode: 'columns', parent: [data], selectedList: this.state.indexing, allowAdd: true } - ); - + if (this.prop.columnSelection === 'single') { + // render option page + $(this.wrapSelector('.vp-ds-option-inner-box')).html(this.templateForSingleSelector()); + // bind column source + // com_generator.vp_bindColumnSource(this, 'data', ['singleColumn'], 'select', false, false); + // vp_bindColumnSource(pageThis, targetId, columnInputIdList, tagType="input", columnWithEmpty=false, columnWithIndex=false) + const columnInputIdList = ['singleColumn']; + if (data === '') { + // reset with no source + columnInputIdList && columnInputIdList.forEach(columnInputId => { + let defaultValue = that.state[columnInputId]; + if (defaultValue === null || defaultValue === undefined) { + defaultValue = ''; + } + // option tags + var tag = $('').attr({ + 'id': columnInputId, + 'class': 'vp-select vp-state' + }); + $(that.wrapSelector('#' + columnInputId)).replaceWith(function() { + return $(tag); + }); + }); + return ; + } + // get result and show on detail box + vpKernel.getColumnList(data).then(function(resultObj) { + try { + let { result, type, msg } = resultObj; + var { list } = JSON.parse(result); + + // columns using suggestInput + columnInputIdList && columnInputIdList.forEach((columnInputId, idx) => { + let defaultValue = that.state[columnInputId]; + if (defaultValue === null || defaultValue === undefined) { + defaultValue = ''; + } + // create tag + var tag = $('').attr({ + 'id': columnInputId, + 'class': 'vp-select vp-state w150' + }); + // make tag + list.forEach((listVar, idx) => { + var option = document.createElement('option'); + $(option).attr({ + 'value':listVar.value, + 'text':listVar.label, + 'data-type':listVar.dtype + }); + // cell metadata test : defaultValue as selected + if (listVar.value === defaultValue) { + $(option).prop('selected', true); + } + option.append(document.createTextNode(listVar.label)); + $(tag).append(option); + }); + $(that.wrapSelector('#' + columnInputId)).replaceWith(function() { + return $(tag); + }); + $(that.wrapSelector('#' + columnInputId)).trigger('change'); + }).catch(function(err) { + vpLog.display(VP_LOG_TYPE.ERROR, 'com_generator - bindColumnSource error ', err) + }); + } catch (e) { + vpLog.display(VP_LOG_TYPE.ERROR, 'com_generator - bindColumnSource: not supported data type. ', e); + } + }); + } else { + // render option page + $(this.wrapSelector('.vp-ds-option-inner-box')).html(this.templateForMultiSelector()); + this._columnSelector = new MultiSelector(this.wrapSelector('.vp-ds-df-multiselector'), + { mode: 'columns', parent: [data], selectedList: this.state.indexing, allowAdd: true } + ); + } // bind event $(this.wrapSelector('#useIndex')).on('change', function() { let checked = $(this).prop('checked'); that.state.useIndex = checked; if (checked === true) { $(that.wrapSelector('.vp-ds-df-multiselector')).hide(); + $(that.wrapSelector('.vp-ds-df-singleselector')).hide(); $(that.wrapSelector('.vp-ds-df-index-box')).show(); } else { $(that.wrapSelector('.vp-ds-df-multiselector')).show(); + $(that.wrapSelector('.vp-ds-df-singleselector')).show(); $(that.wrapSelector('.vp-ds-df-index-box')).hide(); } }); @@ -728,6 +821,7 @@ define([ let { data, dataType, useIndex, + singleColumn, slicingStart1, slicingEnd1, slicingStart2, slicingEnd2, ndRowType, ndColType @@ -742,21 +836,39 @@ define([ code.append('.index'); } else { // use column selector - if (this._columnSelector != null) { - let result = this._columnSelector.getDataList(); - this.state.indexing = result.map(obj => obj.code); // save state - let columnList = []; - result && result.forEach(obj => { - columnList.push(obj.code); - }); - if (columnList.length > 0) { - if (columnList.length == 1) { - // return as Series - code.appendFormat('[{0}]', columnList.join(', ')); - // change datatype to Series - this.state.returnDataType = 'Series'; - } else { - code.appendFormat('[[{0}]]', columnList.join(', ')); + if (this.prop.columnSelection === 'single') { + // single selector + if (this.prop.returnFrameType === 'DataFrame') { + // return as DataFrame + code.appendFormat('[[{0}]]', singleColumn); + } else { + // return as Series + code.appendFormat('[{0}]', singleColumn); + this.state.returnDataType = 'Series'; + } + } else { + // multiple selector + if (this._columnSelector != null) { + let result = this._columnSelector.getDataList(); + this.state.indexing = result.map(obj => obj.code); // save state + let columnList = []; + result && result.forEach(obj => { + columnList.push(obj.code); + }); + if (columnList.length > 0) { + if (columnList.length == 1) { + if (this.prop.returnFrameType === 'DataFrame') { + // return as DataFrame + code.appendFormat('[[{0}]]', columnList.join(', ')); + } else { + // return as Series + code.appendFormat('[{0}]', columnList.join(', ')); + // change datatype to Series + this.state.returnDataType = 'Series'; + } + } else { + code.appendFormat('[[{0}]]', columnList.join(', ')); + } } } } diff --git a/visualpython/js/com/component/ModelEditor.js b/visualpython/js/com/component/ModelEditor.js index da24a5d0..c2fab057 100644 --- a/visualpython/js/com/component/ModelEditor.js +++ b/visualpython/js/com/component/ModelEditor.js @@ -125,7 +125,7 @@ define([ code: '${model}.fit(${fit_featureData})', description: 'Fit Encoder/Scaler to X.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' } + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' } ] }, 'fit_transform': { @@ -134,13 +134,19 @@ define([ code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit Encoder/Scaler to X, then transform X.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, 'transform': { - ...defaultActions['transform'], - description: 'Transform labels to normalized encoding.' + name: 'transform', + label: 'Transform', + code: '${trans_allocate} = ${model}.transform(${trans_featureData})', + description: 'Transform labels to normalized encoding.', + options: [ + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, + { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } + ] } } if (modelType != 'ColumnTransformer') { @@ -152,12 +158,49 @@ define([ code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})', description: 'Transform binary labels back to multi-class labels.', options: [ - { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' } ] } } } + if (modelType == 'LabelEncoder') { + actions = { + ...actions, + 'fit': { + name: 'fit', + label: 'Fit', + code: '${model}.fit(${fit_featureData})', + description: 'Fit Encoder/Scaler to X.', + options: [ + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', + columnSelection: 'single', returnFrameType: 'Series' } + ] + }, + 'fit_transform': { + name: 'fit_transform', + label: 'Fit and transform', + code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', + description: 'Fit Encoder/Scaler to X, then transform X.', + options: [ + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', + columnSelection: 'single', returnFrameType: 'Series' }, + { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } + ] + }, + 'transform': { + name: 'transform', + label: 'Transform', + code: '${trans_allocate} = ${model}.transform(${trans_featureData})', + description: 'Transform labels to normalized encoding.', + options: [ + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', + columnSelection: 'single', returnFrameType: 'Series' }, + { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } + ] + } + } + } if (modelType === 'SMOTE') { actions = { 'fit': { @@ -322,7 +365,7 @@ define([ code: '${model}.fit(${fit_featureData})', description: 'Fit X into an embedded space.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' } + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' } ] }, 'fit_transform': { @@ -331,7 +374,7 @@ define([ code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit X into an embedded space and return that transformed output.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } @@ -346,17 +389,17 @@ define([ code: '${model}.fit(${fit_featureData}, ${fit_targetData})', description: 'Fit the Linear Discriminant Analysis model.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_targetData', label: 'Target Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' } ] }, 'fit_transform': { name: 'fit_transform', label: 'Fit and transform', - code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData}${fit_trans_targetData})', + code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData}, ${fit_trans_targetData})', description: 'Fit to data, then transform it.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_targetData', label: 'Target Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] @@ -367,7 +410,7 @@ define([ code: '${pred_allocate} = ${model}.predict(${pred_featureData})', description: 'Predict class labels for samples in X.', options: [ - { name: 'pred_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'pred_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] }, @@ -377,7 +420,7 @@ define([ code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Project data to maximize class separation.', options: [ - { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } @@ -391,7 +434,7 @@ define([ code: '${model}.fit(${fit_featureData})', description: 'Fit X into an embedded space.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' } + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' } ] }, 'fit_transform': { @@ -400,7 +443,7 @@ define([ code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit the model with X and apply the dimensionality reduction on X.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, @@ -410,7 +453,7 @@ define([ code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})', description: 'Transform data back to its original space.', options: [ - { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' } ] }, @@ -420,7 +463,7 @@ define([ code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Apply dimensionality reduction to X.', options: [ - { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } diff --git a/visualpython/js/m_ml/FitPredict.js b/visualpython/js/m_ml/FitPredict.js index cdd979b9..d48c20c5 100644 --- a/visualpython/js/m_ml/FitPredict.js +++ b/visualpython/js/m_ml/FitPredict.js @@ -41,6 +41,8 @@ define([ method: '', action: {}, optionConfig: {}, + modelEditorType: '', + modelEditorName: '', userOption: '', ...this.state } @@ -315,7 +317,7 @@ define([ } generateCode() { - let { model } = this.state; + let { model, modelType, modelEditorName } = this.state; let code = new com_String(); let replaceDict = {'${model}': model}; @@ -336,6 +338,31 @@ define([ code.appendLine(); code.append(allocateCode); } + // Data Preparation > Scaling + const scalingTypeList = ['StandardScaler', 'RobustScaler', 'MinMaxScaler', 'Normalizer']; + // Dimension Reduction + const dimensionTypeList = ['PCA', 'NMF']; + if (scalingTypeList.includes(modelType) || dimensionTypeList.includes(modelType)) { + // fit_transform, transform returns df_trans also + switch (modelEditorName) { + case 'fit_transform': + const allocatedFitTrans = this.state.fit_trans_allocate || 'trans'; + code.appendLine(); + code.appendLine(); + code.appendFormatLine("df_{0} = pd.DataFrame({1}, columns=[{2}])", allocatedFitTrans, allocatedFitTrans, this.state.fit_trans_featureData); + code.append("df_" + allocatedFitTrans); + break; + case 'transform': + const allocatedTrans = this.state.trans_allocate || 'trans'; + code.appendLine(); + code.appendLine(); + code.appendFormatLine("df_{0} = pd.DataFrame({1}, columns=[{2}])", allocatedTrans, allocatedTrans, this.state.trans_featureData); + code.append("df_" + allocatedTrans); + break; + default: + break; + } + } } return code.toString(); @@ -409,7 +436,7 @@ define([ code: '${model}.fit(${fit_featureData})', description: 'Fit Encoder/Scaler to X.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' } + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' } ] }, 'fit_transform': { @@ -418,13 +445,19 @@ define([ code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit Encoder/Scaler to X, then transform X.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, 'transform': { - ...defaultActions['transform'], - description: 'Transform labels to normalized encoding.' + name: 'transform', + label: 'Transform', + code: '${trans_allocate} = ${model}.transform(${trans_featureData})', + description: 'Transform labels to normalized encoding.', + options: [ + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, + { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } + ] } } if (modelType != 'ColumnTransformer') { @@ -436,12 +469,49 @@ define([ code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})', description: 'Transform binary labels back to multi-class labels.', options: [ - { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' } ] } } } + if (modelType == 'LabelEncoder') { + actions = { + ...actions, + 'fit': { + name: 'fit', + label: 'Fit', + code: '${model}.fit(${fit_featureData})', + description: 'Fit Encoder/Scaler to X.', + options: [ + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', + columnSelection: 'single', returnFrameType: 'Series' } + ] + }, + 'fit_transform': { + name: 'fit_transform', + label: 'Fit and transform', + code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', + description: 'Fit Encoder/Scaler to X, then transform X.', + options: [ + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', + columnSelection: 'single', returnFrameType: 'Series' }, + { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } + ] + }, + 'transform': { + name: 'transform', + label: 'Transform', + code: '${trans_allocate} = ${model}.transform(${trans_featureData})', + description: 'Transform labels to normalized encoding.', + options: [ + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', + columnSelection: 'single', returnFrameType: 'Series' }, + { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } + ] + } + } + } if (modelType === 'SMOTE') { actions = { 'fit': { @@ -606,7 +676,7 @@ define([ code: '${model}.fit(${fit_featureData})', description: 'Fit X into an embedded space.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' } + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' } ] }, 'fit_transform': { @@ -615,7 +685,7 @@ define([ code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit X into an embedded space and return that transformed output.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } @@ -630,7 +700,7 @@ define([ code: '${model}.fit(${fit_featureData}, ${fit_targetData})', description: 'Fit the Linear Discriminant Analysis model.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_targetData', label: 'Target Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' } ] }, @@ -640,7 +710,7 @@ define([ code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData}${fit_trans_targetData})', description: 'Fit to data, then transform it.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_targetData', label: 'Target Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'y' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] @@ -651,7 +721,7 @@ define([ code: '${pred_allocate} = ${model}.predict(${pred_featureData})', description: 'Predict class labels for samples in X.', options: [ - { name: 'pred_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'pred_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'pred_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'pred' } ] }, @@ -661,7 +731,7 @@ define([ code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Project data to maximize class separation.', options: [ - { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } @@ -675,7 +745,7 @@ define([ code: '${model}.fit(${fit_featureData})', description: 'Fit X into an embedded space.', options: [ - { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' } + { name: 'fit_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' } ] }, 'fit_transform': { @@ -684,7 +754,7 @@ define([ code: '${fit_trans_allocate} = ${model}.fit_transform(${fit_trans_featureData})', description: 'Fit the model with X and apply the dimensionality reduction on X.', options: [ - { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'fit_trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'fit_trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] }, @@ -694,7 +764,7 @@ define([ code: '${inverse_allocate} = ${model}.inverse_transform(${inverse_featureData})', description: 'Transform data back to its original space.', options: [ - { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'inverse_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'inverse_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'inv_trans' } ] }, @@ -704,7 +774,7 @@ define([ code: '${trans_allocate} = ${model}.transform(${trans_featureData})', description: 'Apply dimensionality reduction to X.', options: [ - { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X' }, + { name: 'trans_featureData', label: 'Feature Data', component: ['data_select'], var_type: ['DataFrame', 'Series', 'ndarray', 'list', 'dict'], value: 'X', returnFrameType: 'DataFrame' }, { name: 'trans_allocate', label: 'Allocate to', component: ['input'], placeholder: 'New variable', value: 'trans' } ] } From 53c67703a747f7b1748dac70e68772f3d84e9a99 Mon Sep 17 00:00:00 2001 From: visualpython Date: Tue, 14 May 2024 21:45:49 +0900 Subject: [PATCH 11/12] Edited pyproject to build jupyterlab-visualpython package correctly --- jupyterlab/pyproject.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jupyterlab/pyproject.toml b/jupyterlab/pyproject.toml index 11405098..327b3256 100644 --- a/jupyterlab/pyproject.toml +++ b/jupyterlab/pyproject.toml @@ -32,9 +32,13 @@ source = "nodejs" fields = ["description", "authors", "urls"] [tool.hatch.build.targets.sdist] +ignore-vcs = true artifacts = ["jupyterlab-visualpython/labextension"] exclude = [".github", "binder", "build.jupyterlab.sh", "dev-build.jupyterlab.sh"] +[tool.hatch.build.targets.wheel] +only-include = ["jupyterlab-visualpython", "lib", "install.json"] + [tool.hatch.build.targets.wheel.shared-data] "jupyterlab-visualpython/labextension" = "share/jupyter/labextensions/jupyterlab-visualpython" "install.json" = "share/jupyter/labextensions/jupyterlab-visualpython/install.json" From 611a4dd1074afb2bc69b69055b7a998d52a6c48c Mon Sep 17 00:00:00 2001 From: visualpython Date: Tue, 14 May 2024 22:05:12 +0900 Subject: [PATCH 12/12] deploy visualpython 3.0.2 --- build.sh | 4 +- colab/build.colab.sh | 4 +- colab/manifest.json | 2 +- jupyterlab/README.md | 9 +- jupyterlab/Untitled.ipynb | 365 ++++++++++++++++++ jupyterlab/build.jupyterlab.sh | 4 +- jupyterlab/dev-build.jupyterlab.sh | 5 +- jupyterlab/package-lock.json | 5 +- jupyterlab/package.json | 3 +- jupyternotebook/README.md | 9 +- jupyternotebook/build.jupyternotebook.sh | 4 +- jupyternotebook/setup.py | 2 +- visualpython/css/m_ml/modelInfo.css | 4 + visualpython/html/component/dataSelector.html | 4 +- visualpython/js/MainFrame.js | 4 +- visualpython/js/com/com_Config.js | 49 ++- visualpython/js/com/com_Const.js | 2 +- visualpython/js/com/com_generatorV2.js | 5 +- .../js/com/component/MultiSelector.js | 59 +-- visualpython/js/menu/MenuFrame.js | 21 +- 20 files changed, 465 insertions(+), 99 deletions(-) create mode 100644 jupyterlab/Untitled.ipynb diff --git a/build.sh b/build.sh index 0652bfab..2178b3ce 100755 --- a/build.sh +++ b/build.sh @@ -11,8 +11,8 @@ #============================================================================= # Set version and replace it #============================================================================= -VP_ORG_VER=3.0.0 -VP_NEW_VER=3.0.1 +VP_ORG_VER=3.0.1 +VP_NEW_VER=3.0.2 # update version info grep -REil "VP_ORG_VER=.+$" colab/build.colab.sh jupyterlab/build.jupyterlab.sh jupyternotebook/build.jupyternotebook.sh | xargs sed -i "s/VP_ORG_VER=.\+$/VP_ORG_VER=${VP_ORG_VER}/g" diff --git a/colab/build.colab.sh b/colab/build.colab.sh index 060adaa7..2ad68893 100755 --- a/colab/build.colab.sh +++ b/colab/build.colab.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version #============================================================================= -VP_ORG_VER=3.0.0 -VP_NEW_VER=3.0.1 +VP_ORG_VER=3.0.1 +VP_NEW_VER=3.0.2 # update version info # update manifest version with new numbering for new version diff --git a/colab/manifest.json b/colab/manifest.json index cf99ce04..c3509bcc 100644 --- a/colab/manifest.json +++ b/colab/manifest.json @@ -1,7 +1,7 @@ { "name": "Visual Python for Colab", "description": "GUI-based Python code generator for Google Colab as an extension", - "version": "3.0.1", + "version": "3.0.2", "manifest_version": 3, "icons": { "48": "icon.png", diff --git a/jupyterlab/README.md b/jupyterlab/README.md index a03d89a5..6b4bcd90 100644 --- a/jupyterlab/README.md +++ b/jupyterlab/README.md @@ -47,7 +47,7 @@ pip install jupyterlab-visualpython Click orange square button on the right side of Jupyter Lab. -## Getting Started with Jupyter Notebook(>= 7.x) +## Getting Started with Jupyter Notebook 7 ### 1. Requirements @@ -66,13 +66,13 @@ pip install jupyterlab-visualpython Click orange square button on the toolbar of Jupyter Notebook. -## Getting Started with Jupyter Notebook(<=6.x.x) +## Getting Started with Jupyter Notebook (for 6.x.x and older version) ### 1. Requirements Visual Python is an extension to Jupyter Notebook, so you must have Jupyter Notebook installed already. You need old version of Jupyter Notebook under version 6.x.x.
- Python version 3.x -- Jupyter notebook environment <=6.x +- Jupyter notebook environment <= 6.x ### 2. How to Install @@ -152,6 +152,7 @@ All skills from programmers, non-programmers, designers are welcomed. [](https://github.com/llbtl) [](https://github.com/blacklogicdev) [](https://github.com/Minku-Koo) +[](https://github.com/8orrin9) Whoever wants to contribute or join our community,
You can contact us by creating issues on [Issue page](https://github.com/visualpython/visualpython/issues) or using [Discord server](https://discord.gg/PypQrBZWZv). @@ -171,4 +172,4 @@ To create an environment where everyone can learn and use big data analytical sk Love Visual Python?
Your support will help us continue to actively develop and improve Visual Python.☕ -[![donate_banner](https://user-images.githubusercontent.com/83636412/229679467-4fee93a2-d6d2-4229-a53c-80a5eb2b9240.png)](https://github.com/sponsors/visualpython?frequency=recurring) \ No newline at end of file +[![donate_banner](https://user-images.githubusercontent.com/83636412/229679467-4fee93a2-d6d2-4229-a53c-80a5eb2b9240.png)](https://github.com/sponsors/visualpython?frequency=recurring) diff --git a/jupyterlab/Untitled.ipynb b/jupyterlab/Untitled.ipynb new file mode 100644 index 00000000..f7fc91e8 --- /dev/null +++ b/jupyterlab/Untitled.ipynb @@ -0,0 +1,365 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "a891a0cd-ae74-4eaf-84fe-8072d65c83b2", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "db6f55ff-9ddc-4ec1-909b-9582d84f8186", + "metadata": {}, + "outputs": [], + "source": [ + "# Visual Python: Data Analysis > Import\n", + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "%matplotlib inline\n", + "import seaborn as sns" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "e6648223-bd7a-4fcc-8beb-536030401ef6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
sepal_lengthsepal_widthpetal_lengthpetal_widthvariety
05.13.51.40.2Setosa
14.93.01.40.2Setosa
24.73.21.30.2Setosa
34.63.11.50.2Setosa
45.03.61.40.2Setosa
..................
1456.73.05.22.3Virginica
1466.32.55.01.9Virginica
1476.53.05.22.0Virginica
1486.23.45.42.3Virginica
1495.93.05.11.8Virginica
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " sepal_length sepal_width petal_length petal_width variety\n", + "0 5.1 3.5 1.4 0.2 Setosa\n", + "1 4.9 3.0 1.4 0.2 Setosa\n", + "2 4.7 3.2 1.3 0.2 Setosa\n", + "3 4.6 3.1 1.5 0.2 Setosa\n", + "4 5.0 3.6 1.4 0.2 Setosa\n", + ".. ... ... ... ... ...\n", + "145 6.7 3.0 5.2 2.3 Virginica\n", + "146 6.3 2.5 5.0 1.9 Virginica\n", + "147 6.5 3.0 5.2 2.0 Virginica\n", + "148 6.2 3.4 5.4 2.3 Virginica\n", + "149 5.9 3.0 5.1 1.8 Virginica\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Visual Python: Data Analysis > File\n", + "vp_df = pd.read_csv('https://raw.githubusercontent.com/visualpython/visualpython/main/visualpython/data/sample_csv/iris.csv')\n", + "vp_df" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "ae0842cc-baa6-44da-9be6-305ca89f739e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
varietysepal_lengthsepal_widthpetal_lengthpetal_width
0Setosa5.13.51.40.2
1Setosa4.93.01.40.2
2Setosa4.73.21.30.2
3Setosa4.63.11.50.2
4Setosa5.03.61.40.2
..................
145Virginica6.73.05.22.3
146Virginica6.32.55.01.9
147Virginica6.53.05.22.0
148Virginica6.23.45.42.3
149Virginica5.93.05.11.8
\n", + "

150 rows × 5 columns

\n", + "
" + ], + "text/plain": [ + " variety sepal_length sepal_width petal_length petal_width\n", + "0 Setosa 5.1 3.5 1.4 0.2\n", + "1 Setosa 4.9 3.0 1.4 0.2\n", + "2 Setosa 4.7 3.2 1.3 0.2\n", + "3 Setosa 4.6 3.1 1.5 0.2\n", + "4 Setosa 5.0 3.6 1.4 0.2\n", + ".. ... ... ... ... ...\n", + "145 Virginica 6.7 3.0 5.2 2.3\n", + "146 Virginica 6.3 2.5 5.0 1.9\n", + "147 Virginica 6.5 3.0 5.2 2.0\n", + "148 Virginica 6.2 3.4 5.4 2.3\n", + "149 Virginica 5.9 3.0 5.1 1.8\n", + "\n", + "[150 rows x 5 columns]" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Visual Python: Data Analysis > Frame\n", + "vp_df = vp_df.copy()\n", + "vp_df['variety'] = vp_df['variety'].shift(1)\n", + "vp_df.set_index(['variety'], inplace=True)\n", + "vp_df.reset_index(inplace=True)\n", + "vp_df['variety'] = vp_df['variety'].shift(2)\n", + "vp_df['variety'] = vp_df['variety'].fillna(vp_df['variety'].mode()[0])\n", + "vp_df" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/jupyterlab/build.jupyterlab.sh b/jupyterlab/build.jupyterlab.sh index ba89875e..aaee502a 100755 --- a/jupyterlab/build.jupyterlab.sh +++ b/jupyterlab/build.jupyterlab.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version and Basic Files #============================================================================= -VP_ORG_VER=3.0.0 -VP_NEW_VER=3.0.1 +VP_ORG_VER=3.0.1 +VP_NEW_VER=3.0.2 # update version info grep -REil "\"version\": \"${VP_ORG_VER}\"" package.json | xargs sed -i "s/\"version\": \"${VP_ORG_VER//\./\\.}\"/\"version\": \"${VP_NEW_VER}\"/g" diff --git a/jupyterlab/dev-build.jupyterlab.sh b/jupyterlab/dev-build.jupyterlab.sh index 7ebac489..5c926d40 100755 --- a/jupyterlab/dev-build.jupyterlab.sh +++ b/jupyterlab/dev-build.jupyterlab.sh @@ -16,7 +16,10 @@ rm -rf lib/visualpython cp -r ../visualpython lib/visualpython # convert text-loader, raw-loader, css-loader -grep -rl "__VP_TEXT_LOADER__" lib/visualpython/js/* | xargs sed -i "s/__VP_TEXT_LOADER__('\(.\+\)')\(.\+$\)/'!!text-loader!\1'\2/g" +# __VP_TEXT_LOADER__('vp/path/textfile'), -> '!!text-loader!vp/path/textfile', +# __VP_RAW_LOADER('vp/path/rawfile.json'), -> 'vp/path/rawfile.json', +# __VP_CSS_LOADER('vp/path/cssfile'), -> 'vp/path/cssfile.css', +grep -rl "__VP_TEXT_LOADER__" lib/visualpython/js/* | xargs sed -i "s/__VP_TEXT_LOADER__('\(.\+\)')\(.\+$\)/'\!\!text-loader\!\1'\2/g" grep -rl "__VP_RAW_LOADER__" lib/visualpython/js/* | xargs sed -i "s/__VP_RAW_LOADER__('\(.\+\)')\(.\+$\)/'\1'\2/g" grep -rl "__VP_CSS_LOADER__" lib/visualpython/js/* | xargs sed -i "s/__VP_CSS_LOADER__('\(.\+\)')\(.\+$\)/'\1.css'\2/g" diff --git a/jupyterlab/package-lock.json b/jupyterlab/package-lock.json index d166e82c..f1b79d4f 100644 --- a/jupyterlab/package-lock.json +++ b/jupyterlab/package-lock.json @@ -1,18 +1,19 @@ { "name": "jupyterlab-visualpython", - "version": "3.0.0", + "version": "3.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "jupyterlab-visualpython", - "version": "3.0.0", + "version": "3.0.2", "license": "GPLv3 with Visual Python special exception", "dependencies": { "@jupyterlab/application": "^4.1.0-alpha.2", "@jupyterlab/cells": "^4.0.5", "@jupyterlab/notebook": "^4.0.5", "@jupyterlab/ui-components": "^4.0.5", + "css-loader": "^6.7.1", "jquery": "^3.6.3", "jquery-ui": "^1.13.2", "jquery-ui-bundle": "^1.12.1-migrate", diff --git a/jupyterlab/package.json b/jupyterlab/package.json index 2f1fc4a1..16ce1cb3 100644 --- a/jupyterlab/package.json +++ b/jupyterlab/package.json @@ -1,6 +1,6 @@ { "name": "jupyterlab-visualpython", - "version": "3.0.1", + "version": "3.0.2", "description": "GUI-based Python code generator for Jupyter Lab as an extension", "keywords": [ "jupyter", @@ -44,6 +44,7 @@ "@jupyterlab/cells": "^4.0.5", "@jupyterlab/notebook": "^4.0.5", "@jupyterlab/ui-components": "^4.0.5", + "css-loader": "^6.7.1", "jquery": "^3.6.3", "jquery-ui": "^1.13.2", "jquery-ui-bundle": "^1.12.1-migrate", diff --git a/jupyternotebook/README.md b/jupyternotebook/README.md index a03d89a5..6b4bcd90 100644 --- a/jupyternotebook/README.md +++ b/jupyternotebook/README.md @@ -47,7 +47,7 @@ pip install jupyterlab-visualpython Click orange square button on the right side of Jupyter Lab. -## Getting Started with Jupyter Notebook(>= 7.x) +## Getting Started with Jupyter Notebook 7 ### 1. Requirements @@ -66,13 +66,13 @@ pip install jupyterlab-visualpython Click orange square button on the toolbar of Jupyter Notebook. -## Getting Started with Jupyter Notebook(<=6.x.x) +## Getting Started with Jupyter Notebook (for 6.x.x and older version) ### 1. Requirements Visual Python is an extension to Jupyter Notebook, so you must have Jupyter Notebook installed already. You need old version of Jupyter Notebook under version 6.x.x.
- Python version 3.x -- Jupyter notebook environment <=6.x +- Jupyter notebook environment <= 6.x ### 2. How to Install @@ -152,6 +152,7 @@ All skills from programmers, non-programmers, designers are welcomed. [](https://github.com/llbtl) [](https://github.com/blacklogicdev) [](https://github.com/Minku-Koo) +[](https://github.com/8orrin9) Whoever wants to contribute or join our community,
You can contact us by creating issues on [Issue page](https://github.com/visualpython/visualpython/issues) or using [Discord server](https://discord.gg/PypQrBZWZv). @@ -171,4 +172,4 @@ To create an environment where everyone can learn and use big data analytical sk Love Visual Python?
Your support will help us continue to actively develop and improve Visual Python.☕ -[![donate_banner](https://user-images.githubusercontent.com/83636412/229679467-4fee93a2-d6d2-4229-a53c-80a5eb2b9240.png)](https://github.com/sponsors/visualpython?frequency=recurring) \ No newline at end of file +[![donate_banner](https://user-images.githubusercontent.com/83636412/229679467-4fee93a2-d6d2-4229-a53c-80a5eb2b9240.png)](https://github.com/sponsors/visualpython?frequency=recurring) diff --git a/jupyternotebook/build.jupyternotebook.sh b/jupyternotebook/build.jupyternotebook.sh index 8659e4af..a14b23b9 100755 --- a/jupyternotebook/build.jupyternotebook.sh +++ b/jupyternotebook/build.jupyternotebook.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version and Basic Files #============================================================================= -VP_ORG_VER=3.0.0 -VP_NEW_VER=3.0.1 +VP_ORG_VER=3.0.1 +VP_NEW_VER=3.0.2 # update version info grep -REil ${VP_ORG_VER//\./\\.} setup.py visualpython/js/com/com_Config.js visualpython/js/com/com_Const.js | xargs sed -i --follow-symlinks "s/${VP_ORG_VER//\./\\.}/${VP_NEW_VER}/g" diff --git a/jupyternotebook/setup.py b/jupyternotebook/setup.py index bf0fb000..8fe43b1f 100644 --- a/jupyternotebook/setup.py +++ b/jupyternotebook/setup.py @@ -10,7 +10,7 @@ setup( name = name, - version = '3.0.1', + version = '3.0.2', packages = find_packages(), package_data = {"": ["*"], 'visualpython' : ['visualpython.yaml', 'README.md']}, scripts = ['visualpython/bin/visualpy', 'visualpython/bin/visualpy.bat'], diff --git a/visualpython/css/m_ml/modelInfo.css b/visualpython/css/m_ml/modelInfo.css index 2975f521..2bd9d885 100644 --- a/visualpython/css/m_ml/modelInfo.css +++ b/visualpython/css/m_ml/modelInfo.css @@ -1,3 +1,7 @@ +.vp-model-select-box { + grid-column-gap: 5px; + align-items: start; +} .vp-ins-select-title { font-weight: bold; color: var(--vp-font-highlight); diff --git a/visualpython/html/component/dataSelector.html b/visualpython/html/component/dataSelector.html index 8090aace..2e402219 100644 --- a/visualpython/html/component/dataSelector.html +++ b/visualpython/html/component/dataSelector.html @@ -8,7 +8,7 @@
-
+
@@ -22,7 +22,7 @@
-
+
diff --git a/visualpython/js/MainFrame.js b/visualpython/js/MainFrame.js index 20163472..b16149b1 100644 --- a/visualpython/js/MainFrame.js +++ b/visualpython/js/MainFrame.js @@ -520,10 +520,10 @@ define([ let parentBlock = null; let prevBlock = null; loadStateList.forEach(obj => { - let { blockType, menuId, menuState, menuConfig, argIdx, position, afterAction } = obj; + let { file, blockType, menuId, menuState, menuConfig, argIdx, position, afterAction } = obj; // get OptionComponent Object // LAB: relative path needed - let OptionComponent = require('./' + menuConfig.file); + let OptionComponent = require('./' + file); if (OptionComponent) { let taskState = menuState.taskState; let blockState = menuState.blockState; diff --git a/visualpython/js/com/com_Config.js b/visualpython/js/com/com_Config.js index a8f8047e..9062699a 100644 --- a/visualpython/js/com/com_Config.js +++ b/visualpython/js/com/com_Config.js @@ -270,8 +270,7 @@ define([ vp_config_version: '1.0.0', vp_signature: 'VisualPython', vp_position: {}, - // CHROME: default to display vp - vp_section_display: true, + vp_section_display: false, vp_note_display: false, vp_menu_width: Config.MENU_MIN_WIDTH, vp_note_width: Config.BOARD_MIN_WIDTH @@ -575,7 +574,7 @@ define([ that._checkMounted().then(function() { that._readFromColab(configKey).then(function(result) { let data = result; - if (data == undefined || data == {}) { + if (data == undefined || (data instanceof Object && Object.keys(data).length === 0)) { resolve(data); return; } @@ -583,7 +582,7 @@ define([ resolve(data); return; } - if (Object.keys(data).length > 0) { + if (data instanceof Object && Object.keys(data).length > 0) { resolve(data[dataKey]); return; } @@ -599,7 +598,7 @@ define([ // LAB: use local .visualpython files that._readFromLab(configKey).then(function(result) { let data = result; - if (data == undefined || data == {}) { + if (data == undefined || (data instanceof Object && Object.keys(data).length === 0)) { resolve(data); return; } @@ -607,7 +606,7 @@ define([ resolve(data); return; } - if (Object.keys(data).length > 0) { + if (data instanceof Object && Object.keys(data).length > 0) { resolve(data[dataKey]); return; } @@ -869,6 +868,40 @@ define([ return Config.version; } + checkVersionTimestamp = function() { + let that = this; + // check version timestamp + let nowDate = new Date(); + this.getData('version_timestamp', 'vpcfg').then(function(data) { + let doCheckVersion = false; + vpLog.display(VP_LOG_TYPE.DEVELOP, 'Checking its version timestamp... : ' + data); + if (data == undefined || (data instanceof Object && Object.keys(data).length === 0)) { + // no timestamp, check version + doCheckVersion = true; + } else if (data != '') { + let lastCheck = new Date(parseInt(data)); + let diffCheck_now = new Date(nowDate.getFullYear(), nowDate.getMonth() + 1, nowDate.getDate()); + let diffCheck_last = new Date(lastCheck.getFullYear(), lastCheck.getMonth() + 1, lastCheck.getDate()); + + let diff = Math.abs(diffCheck_now.getTime() - diffCheck_last.getTime()); + diff = Math.ceil(diff / (1000 * 3600 * 24)); + + if (diff >= 1) { + // if More than 1 day passed, check version + doCheckVersion = true; + } + } + + // check version and update version_timestamp + if (doCheckVersion == true) { + that.checkVpVersion(true); + } + + }).catch(function(err) { + vpLog.display(VP_LOG_TYPE.ERROR, err); + }) + } + checkVpVersion(background=false) { let that = this; let nowVersion = this.getVpInstalledVersion(); @@ -923,6 +956,8 @@ define([ switch (clickedBtnIdx) { case 0: // cancel + // update version_timestamp + that.setData({ 'version_timestamp': new Date().getTime() }, 'vpcfg'); break; case 1: // update @@ -1038,7 +1073,7 @@ define([ /** * Version */ - Config.version = "3.0.1"; + Config.version = "3.0.2"; /** * Type of mode diff --git a/visualpython/js/com/com_Const.js b/visualpython/js/com/com_Const.js index d81b76b7..fbd18788 100644 --- a/visualpython/js/com/com_Const.js +++ b/visualpython/js/com/com_Const.js @@ -19,7 +19,7 @@ define ([ class Constants { } Constants.TOOLBAR_BTN_INFO = { - HELP: "Visual Python 3.0.1" + HELP: "Visual Python 3.0.2" , ICON: "vp-main-icon" , ID: "vpBtnToggle" , NAME: "toggle-vp" diff --git a/visualpython/js/com/com_generatorV2.js b/visualpython/js/com/com_generatorV2.js index b793c226..42e6c760 100644 --- a/visualpython/js/com/com_generatorV2.js +++ b/visualpython/js/com/com_generatorV2.js @@ -139,7 +139,7 @@ define([ package.options && package.options.forEach(function(o, i) { var obj = JSON.parse(JSON.stringify(o)); let newTag = vp_createTag(pageThis, obj, state); - if (obj.required) { + if (obj.required === true || obj.output === true) { tblInput.append(newTag); } else { tblOption.append(newTag); @@ -147,6 +147,9 @@ define([ }); // TODO: userOption + if (package.code.includes('${etc}')) { + + } bindMultiSelector(pageThis); bindAutoComponentEvent(pageThis); diff --git a/visualpython/js/com/component/MultiSelector.js b/visualpython/js/com/component/MultiSelector.js index 33546d79..d9d3d9fa 100644 --- a/visualpython/js/com/component/MultiSelector.js +++ b/visualpython/js/com/component/MultiSelector.js @@ -443,62 +443,6 @@ define([ that._bindItemClickEvent(); }); - // item indexing - $(this.wrapSelector('.' + APP_SELECT_ITEM)).on('click', function(event) { - var dataIdx = $(this).attr('data-idx'); - var idx = $(this).index(); - var added = $(this).hasClass('added'); // right side added item? - var selector = ''; - - // remove selection for select box on the other side - if (added) { - // remove selection for left side - $(that.wrapSelector('.' + APP_SELECT_ITEM + ':not(.added)')).removeClass('selected'); - // set selector - selector = '.added'; - } else { - // remove selection for right(added) side - $(that.wrapSelector('.' + APP_SELECT_ITEM + '.added')).removeClass('selected'); - // set selector - selector = ':not(.added)'; - } - - if (vpEvent.keyManager.keyCheck.ctrlKey) { - // multi-select - that.pointer = { start: idx, end: -1 }; - $(this).toggleClass('selected'); - } else if (vpEvent.keyManager.keyCheck.shiftKey) { - // slicing - var startIdx = that.pointer.start; - - if (startIdx == -1) { - // no selection - that.pointer = { start: idx, end: -1 }; - } else if (startIdx > idx) { - // add selection from idx to startIdx - var tags = $(that.wrapSelector('.' + APP_SELECT_ITEM + selector)); - for (var i = idx; i <= startIdx; i++) { - $(tags[i]).addClass('selected'); - } - that.pointer = { start: startIdx, end: idx }; - } else if (startIdx <= idx) { - // add selection from startIdx to idx - var tags = $(that.wrapSelector('.' + APP_SELECT_ITEM + selector)); - for (var i = startIdx; i <= idx; i++) { - $(tags[i]).addClass('selected'); - } - that.pointer = { start: startIdx, end: idx }; - } - } else { - // single-select - that.pointer = { start: idx, end: -1 }; - // un-select others - $(that.wrapSelector('.' + APP_SELECT_ITEM + selector)).removeClass('selected'); - // select this - $(this).addClass('selected'); - } - }); - // item indexing - add all $(this.wrapSelector('.' + APP_SELECT_ADD_ALL_BTN)).on('click', function(event) { $(that.wrapSelector('.' + APP_SELECT_BOX + '.left .' + APP_SELECT_ITEM)).appendTo( @@ -702,6 +646,7 @@ define([ let newItemIndex = this.dataList.length; var targetTag = $(`
${newItemName} +
`); $(targetTag).appendTo( $(this.wrapSelector('.' + APP_SELECT_BOX + '.right')) @@ -711,6 +656,8 @@ define([ $(this.wrapSelector('.' + APP_SELECT_ITEM)).removeClass('selected'); // clear item input $(this.wrapSelector('.vp-cs-add-item-name')).val(''); + // bind click event + this._bindItemClickEvent(); // bind draggable this.bindDraggable(); } diff --git a/visualpython/js/menu/MenuFrame.js b/visualpython/js/menu/MenuFrame.js index 05813295..386916a3 100644 --- a/visualpython/js/menu/MenuFrame.js +++ b/visualpython/js/menu/MenuFrame.js @@ -205,19 +205,19 @@ define([ return {}; } - getMenuLibrary(menuId, libraries=this.menuLibraries) { + getMenuLibrary(menuId, libraries=this.menuLibrariesFlatten) { for (var i=0; i < libraries.length; i++) { var item = libraries[i]; if (item) { if (item.id === menuId) { return item; } - if (item.type === 'package') { - var result = this.getMenuLibrary(menuId, item.item); - if (result) { - return result; - } - } + // if (item.type === 'package') { + // var result = this.getMenuLibrary(menuId, item.item); + // if (result) { + // return result; + // } + // } } } return null; @@ -252,7 +252,12 @@ define([ var that = this; var body = group.getBody(); var item = group.getItem(); + var state = group.getState(); item && item.forEach(child => { + // remember parent to navigate its parent menu + var category = state.category?(state.category + ' > ' + state.name):state.name; + child['category'] = category; + if (child.type == 'package') { // packages : MenuGroup var menuGroup = new MenuGroup($(body), child); @@ -298,7 +303,7 @@ define([ }); let functionList = this.menuLibrariesFlatten.map(menu => { - return { label: menu.name, value: menu.name, ...menu } + return { label: menu.name, value: menu.name, dtype: menu.category, ...menu } }); // render searchbox let searchBox = new SuggestInput();