[Jupyter Notebook]EChart画图以及如何获取Python定义的变量

1. 画一个基础的echart

目前发现有两种方法可以完成一个简单的Echart.

  • 方法一

一种是使用%%html,在一个cell中写完HTML+JS代码。例如,

%%html
<div id="main" style="width:700px;height:400px"></div>
<script src="js/echarts.min.js"></script>

<script>

<!-- do something -->
<!-- inital echart -->  

</script>
  • 方法2

另一种,%%javascript%%html结合使用,各司其职。

Jupyter Notebook自带requirejs,可以使用requirejs来引入外部js文件.

%%javascript

//配置js源地址,也可以使用本地的js文件
requirejs.config({
     paths:{
            'echarts': ["http://echarts.baidu.com/dist/echarts.min"],  //末尾会自动添加.js, 这里一定要去掉,否则引用失败  
             'jquery': ["https://code.jquery.com/jquery-3.3.1.min"],
         }
});
require(["ecahrts", "jquery"], function(echarts, jquery){
    
    // do something  
    // initial echart
});

2. 使用Python定义的变量

使用Notebook画图时,变量大多是之前用python脚本算好的。那么,要使Notebook中画echart实用,要解决的关键问题就是,如何使用python定义的变量画图.

Notebook javascript自带的IPython模块,让我们可以在js脚本中执行python的代码。
如图:

[Jupyter Notebook]EChart画图以及如何获取Python定义的变量

Ipython.notebook.kernel.execute允许设置callbacks, 在callbacks中可以对代码执行的output进行相关处理。

var code = "print ('Hello World')";    
    var callbacks = {    
    iopub : {
        output: function(data){
            var res = data.content.text;
            // `res` is 'Hello World'
            // do something
        }
    }
    };
execute(code, callbacks);

由此,我的基本思路就是通过处理output获取Python定义的变量。
单纯的print出来,当变量是list时,格式会有问题。所以通过json.dumps对数据进行了转换

var code = "print(json.dumps(["+ paramNames.join() +"]))";  
//paraNames是变量名组成的list
var callbacks = {    
    iopub : {
        output: function(data){
            var res = JSON.parse(data.content.text.trim()); 
            // do something
        }
    }

3. 完整代码

整理前面的思路, 将引用js,传递变量等部分,整理为一个js文件. 以后只需要引用这个js文件即可。

这是一个简陋且高度定制化的方法,目前基本满足我的日常工作,如果你有更好的意见或是建议,欢迎指出


//   my-echart.js  

requirejs.config({
     paths:{
            'echarts': ["http://echarts.baidu.com/dist/echarts.min"],
             'jquery': ["https://code.jquery.com/jquery-3.3.1.min"],
         }
});

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function execute(code, callbacks) {
    var kernel = IPython.notebook.kernel;
    // notebook分享给其他人时,为避免kernel未启动js报错,会等待kernel ready再画图
    while(!kernel){
    console.log('Taking a break...');
    await sleep(2000);
    console.log('Two seconds later');
    var kernel = IPython.notebook.kernel;
    }
    console.log("kernel has ready");
    IPython.notebook.kernel.execute("import json");
    IPython.notebook.kernel.execute(code,callbacks);
}

// 按顺序将echart option中的变量替换为callbacks获取的变量
function formatOption(option) {
    var string = JSON.stringify(option)
    var args = arguments[1];
    var pattern = new RegExp('([", \'])\%([1-'+ args.length +'])([",\'])', "g");
    var str_with_data = String(string).replace(pattern, 
                                               function(match,p1,index) {
        return JSON.stringify(args[index-1]);
    });
    return JSON.parse(str_with_data)
};


function loadChart(option,chartId){
    
    require(["jquery","echarts"],function(jquery,echarts){    
    var myChart = echarts.init(document.getElementById(chartId));
    myChart.clear();
    
    myChart.setOption(option);

});    
};

// MAIN-FUNCTION
async function newEChart(chartId, option, paramNames){
    
    var code = "print(json.dumps(["+ paramNames.join() +"]))";    
    var callbacks = {    
    iopub : {
        output: function(data){
            var res = JSON.parse(data.content.text.trim()); 
            var optionWithData = formatOption(option,res);
            loadChart(optionWithData, chartId);
        }
    }
    };
    execute(code, callbacks);
};

4. 使用范例

  • 定义数据
x = ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
data = [5, 20, 36, 10, 10, 20]
  • 定义模块
%%html
<div id="main" style="width:700px;height:400px"></div>
<script src="js/my-echarts.js"></script>   
  • initial Chart
%%javascript

// 指定图表的配置项和数据
var option = {
    title: {
        text: 'ECharts 入门示例'
    },
    tooltip: {},
    legend: {
        data:['销量']
    },
    xAxis: {
        data: "%1"   // 会被替换为 x
    },
    yAxis: {},
    series: [{
        name: '销量',
        type: 'bar',
        data: "%2"  // 会被替换为 data
    }]
};


newEChart("main",option,["x","data"]);
// params:  ID, option, parameter names list