Nodebooks: Introducing Node.js Data Science Notebooks

Python and Node.js in the same Jupyter notebook (part 1)

Glynn Bird
Sep 6, 2017 · 5 min read

Notebooks

Notebooks (that’s Jupyter/IPython Notebooks, not Moleskine® notebooks) are where data scientists process, analyse, and visualise data in an iterative, collaborative environment. Like other developers, I am not a data scientist, but I do like the idea of having a scratchpad where I can write some code, iteratively work on some algorithms, and visualise the results quickly.

Installing

Install both pixiedust and pixiedust_node using pip, the Python package manager. In a Jupyter Notebook cell:

!pip install pixiedust
!pip install pixiedust_node

Using pixiedust_node

Now we can import pixiedust_node into our notebook:

import pixiedust_node
%%node
var date = new Date();
print(date);
// "2017-05-15T14:02:28.207Z"
The JS code and its output, as rendered in an IPython Notebook cell.

Printing JavaScript variables

Calling the print function within your JavaScript code is the same as calling print in your Python code.

%%node
var x = { a:1, b:'two', c: true };
print(x);
// {"a": 1, "b": "two", "c": true}

Using PixieDust display() to visualise data

You can also use PixieDust’s display function to render data graphically:

%%node
var data = [];
for (var i = 0; i < 1000; i++) {
var x = 2*Math.PI * i/ 360;
var obj = {
x: x,
i: i,
sin: Math.sin(x),
cos: Math.cos(x),
tan: Math.tan(x)
};
data.push(obj);
}
display(data);
Using PixieDust’s display UI to refine a visualisation

Adding npm modules

There are thousands of libraries and tools in the npm repository, Node.js’s package manager. It’s essential that we can install npm libraries and use them in our notebook code.

npm.install('request');
%%node
var request = require('request');
var r = {
method:'GET',
url: 'http://api.open-notify.org/iss-now.json',
json: true
};
request(r, function(err, req, body) {
print(body);
});
// {"timestamp": 1494857069, "message": "success", "iss_position": {"latitude": "24.0980", "longitude": "-84.5517"}}
%%node
var request = require('request');
var getPosition = function(callback) {
var r = {
method:'GET',
url: 'http://api.open-notify.org/iss-now.json',
json: true
};
request(r, function(err, req, body) {
var obj = null;
if (!err) {
obj = body.iss_position
obj.latitude = parseFloat(obj.latitude);
obj.longitude = parseFloat(obj.longitude);
obj.time = new Date().getTime();
}
callback(err, obj);
});
};
%%node
getPosition(function(err, data) {
print(data);
});
// {"latitude": 50.5736, "longitude": -99.3493, "time": 1494422942373}

Promise me a miracle

If you prefer to work with JavaScript Promises when writing asynchronous code, then that’s okay too. Let’s rewrite our getPosition function to return a Promise. First we're going to install the request-promise module from npm:

npm.install( ('request', 'request-promise') )
%%node
var request = require('request-promise');
var getPosition = function(callback) {
var r = {
method:'GET',
url: 'http://api.open-notify.org/iss-now.json',
json: true
};
return request(r).then(function(body) {
var obj = null;
obj = body.iss_position
obj.latitude = parseFloat(obj.latitude);
obj.longitude = parseFloat(obj.longitude);
obj.time = new Date().getTime();
return obj;
});
};
%%node
getPosition().then(function(data) {
print(data);
});
// {"latitude": 20.7734, "longitude": -81.5809, "time": 1494857142842}
%%node
getPosition().then(print);
// {"latitude": 20.7734, "longitude": -81.5809, "time": 1494857142842}

Next time

In the next part of this three-part series, we’ll look at sharing variables between Node.js and Python code and interacting with databases from our notebook.

Links

IBM CODAIT

Things we made with data at IBM’s Center for Open Source Data and AI Technologies.

Glynn Bird

Written by

Developer @ IBM. https://glynnbird.com

IBM CODAIT

Things we made with data at IBM’s Center for Open Source Data and AI Technologies.