Typescript Notebook Example

This book uses typescript-jupyter-kernel to execute Typescript code, which gives us both the advantages of Node.js and Browser all under Jupyter.

Accessing the Filesystem

For example we can load some csv data from the local filesystem using fs and parse the data using d3-dsv which for convenience has been integrated into the Typescript kernel and is accessible as jupyter.data:

import { readFileSync } from 'fs';

const { csvParse } = jupyter.data;

const rawData = readFileSync('./data.csv').toString('utf-8');

const parsedData = csvParse(rawData);

jupyter.out(parsedData);
[
  {
    Country: 'Luxembourg',
    'Hourly Minimum Wage in USD (2015)': '11.9',
    'Hourly Minimum Wage in USD (2016)': '11.8',
    'Hourly Minimum Wage in USD (2017)': '12.1',
    'Hourly Minimum Wage in USD (2018)': '12',
    'Hourly Minimum Wage in USD (2019)': '12.2',
    'Hourly Minimum Wage in USD (2020)': '12.4'
  },
  {
    Country: 'Australia',
    'Hourly Minimum Wage in USD (2015)': '11.6',
    'Hourly Minimum Wage in USD (2016)': '11.8',
    'Hourly Minimum Wage in USD (2017)': '11.9',
    'Hourly Minimum Wage in USD (2018)': '12',
    'Hourly Minimum Wage in USD (2019)': '12.2',
    'Hourly Minimum Wage in USD (2020)': '12.4'
  },
  {
    Country: 'France',
    'Hourly Minimum Wage in USD (2015)': '12',
    'Hourly Minimum Wage in USD (2016)': '12.1',
    'Hourly Minimum Wage in USD (2017)': '12.1',
    'Hourly Minimum Wage in USD (2018)': '12',
    'Hourly Minimum Wage in USD (2019)': '12.1',
    'Hourly Minimum Wage in USD (2020)': '12.1'
  },
  {
    Country: 'Germany',
    'Hourly Minimum Wage in USD (2015)': '11.3',
    'Hourly Minimum Wage in USD (2016)': '11.3',
    'Hourly Minimum Wage in USD (2017)': '11.6',
    'Hourly Minimum Wage in USD (2018)': '11.4',
    'Hourly Minimum Wage in USD (2019)': '11.7',
    'Hourly Minimum Wage in USD (2020)': '11.8'
  },
  {
    Country: 'New Zealand',
    'Hourly Minimum Wage in USD (2015)': '9.8',
    'Hourly Minimum Wage in USD (2016)': '10.1',
    'Hourly Minimum Wage in USD (2017)': '10.2',
    'Hourly Minimum Wage in USD (2018)': '10.4',
    'Hourly Minimum Wage in USD (2019)': '11',
    'Hourly Minimum Wage in USD (2020)': '11.6'
  },
  columns: [
    'Country',
    'Hourly Minimum Wage in USD (2015)',
    'Hourly Minimum Wage in USD (2016)',
    'Hourly Minimum Wage in USD (2017)',
    'Hourly Minimum Wage in USD (2018)',
    'Hourly Minimum Wage in USD (2019)',
    'Hourly Minimum Wage in USD (2020)'
  ]
]

Rendering Data to HTML

We can take the previous code and use jupyter.dom (which is simply a JSDOM instance) to construct and render an HTML table:

import { readFileSync } from 'fs';

const {
  data: {
    csvParseRows
  },
  dom: {
    window: {
      document
    }
  },
  renderDom,
} = jupyter;

const rawData = readFileSync('./data.csv').toString('utf-8');

const [
  columnHeaders,
  ...rows
] = csvParseRows(rawData);

const table = document.createElement('table');
const tableHeader = document.createElement('thead');
const tableHeaderRow = document.createElement('tr');
const tableBody = document.createElement('tbody');

columnHeaders.forEach(
  (h) => {
    const columnHeader = document.createElement('th');
    columnHeader.innerHTML = h;

    tableHeaderRow.appendChild(columnHeader);
  }
);

tableHeader.appendChild(tableHeaderRow);

rows.forEach(
  (r) => {
    const rowElement = document.createElement('tr');

    r.forEach(
      (d) => {
        const dataElement = document.createElement('td');
        dataElement.innerHTML = d;

        rowElement.appendChild(dataElement);
      }
    );

    tableBody.appendChild(rowElement);
  }
);

table.appendChild(tableHeader);

table.appendChild(tableBody);

document.body.appendChild(table);

renderDom();
CountryHourly Minimum Wage in USD (2015)Hourly Minimum Wage in USD (2016)Hourly Minimum Wage in USD (2017)Hourly Minimum Wage in USD (2018)Hourly Minimum Wage in USD (2019)Hourly Minimum Wage in USD (2020)
Luxembourg11.911.812.11212.212.4
Australia11.611.811.91212.212.4
France1212.112.11212.112.1
Germany11.311.311.611.411.711.8
New Zealand9.810.110.210.41111.6

Visualizing Data

It should be noted that destructuring the document out of jupyter on the previous example was done strictly for demonstrational purposes, as window, navigator, and document are exposed as global variables.

In the following example we can take advantage of the aforementioned fact in order to render a chart using echarts (which was added to this book’s package.json as a dependency) since echarts expects the document object to be available globally:

import { readFileSync } from 'fs';
import * as echarts from 'echarts';

// Get the HTML body
const { body } = document;

// Add an <h2> heading to the body
// NOTE: using Unicode Identity for the emoji since emojis in code
//       can break the communication between Jupyter and the kernel
body.appendChild(document.createElement('h2'));
body.querySelector('h2').innerHTML = 'Top 5 Countries with Highest Minimum Hourly Wage \xF0\x9F\x8C\x8E';

// Load a CSV file from the local filesystem
const csvString = readFileSync('./data.csv').toString('utf-8');

// Use a local js browser library to parse CSV data
const { csvParseRows } = jupyter.data;
const [
  csvHeaders,
  ...csvDataRows
] = csvParseRows(csvString);

csvHeaders.shift(); // Remove unnecesary "Country" header

const countries = csvDataRows.map((r) => r[0]); // Extract country from each row

// Map rows into series compatible with ECharts
const series = csvDataRows.map(
  ([name, ...values]) => (
    {
      name,
      type: 'line',
      data: values.map((i) => parseFloat(i))
    }
  )
);

// Create a container div for a chart
const chartContainer = document.createElement('div');
chartContainer.style = 'width: 800px; height: 600px; margin-top: 20px;';
Object.defineProperty(chartContainer, 'clientWidth', {value: 800});
Object.defineProperty(chartContainer, 'clientHeight', {value: 600});

// Initialize an echarts instance using the chart container div
var myChart = echarts.init(
  chartContainer,
  null,
  {
    renderer: 'svg',
  },
);

const chartOptions = {
  legend: {
    data: countries
  },
  grid: {
    left: '80px',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    boundaryGap: true,
    data: csvHeaders,
    axisLabel: {
      interval: 0,
      rotate: 45 // If the label names are too long you can manage this by rotating the label.
    },
    axisLine: {
      lineStyle: {
        color: '#14ab3c'
      }
    },
    splitLine: {
      show: true,
      lineStyle: {
        type: 'dashed'
      }
    }
  },
  yAxis: {
    type: 'value',
    min: 8,
    max: 14,
    axisLine: {
      lineStyle: {
        color: '#14ab3c',
        type: 'solid'
      }
    }
  },
  series
};

// Load the CSV data into a bar chart
myChart.setOption(chartOptions);

// Append the chart container div to the body
body.appendChild(chartContainer);

jupyter.renderDom();

Top 5 Countries with Highest Minimum Hourly Wage 🌎

891011121314Hourly Minimum Wage in USD (2015)Hourly Minimum Wage in USD (2016)Hourly Minimum Wage in USD (2017)Hourly Minimum Wage in USD (2018)Hourly Minimum Wage in USD (2019)Hourly Minimum Wage in USD (2020)LuxembourgAustraliaFranceGermanyNew Zealand