Search Lessons, Code Snippets, and Videos
search by algolia
X
#native_cta# #native_desc# Sponsored by #native_company#

Realtime Charts With Plot.ly

Episode 39 written by Jeff Delaney
full courses and content on fireship.io

With the rise of big data and deep learning, the importance of data visualization has never been more important. I am a huge fan of data science competitions and think Plot.ly offers the best open source JS library for creating charts, graphs, heatmaps, etc.

In this episode, we are going to add Plot.ly to our Angular4 application. To really make things exciting, are going to wire up realtime data on the backend with Firebase and update the charts asynchronously.

Adding Plot.ly to Angular

There are some issues using plotly.js node package with webpack, but we can still use the library by loading it at build time with the Angular CLI.

install plotly.js

First, install the Plotly.js node package.

npm install plotly.ls --save

angular-cli.json

Then add it to the angular CLI

Make sure to restart your local server at this point to ensure the script is loaded into your project. Also, if you don’t need the full plotly library, you can use a smaller subset, such as plotly-finance or plotly-basic. You will find these scripts in node_modules/plotly.js/dist/

typings.d.ts

Lastly, we need to register the Plotly class with TypeScript in the typings file.

declare var Plotly: any;

The Most Basic Example

Let’s start with a basic hello world static chart.

a basic plotly chart in angular4

ng g component cool-chart

cool-chart.component.ts

First, we need to let Angular access the div in the HTML where the chart will be displayed. We can do this by using the following syntax in the HTML

<div #chart>
<!-- Chart will appear here -->
</div>

Then we can call @ViewChild('chart') to get a hold of that div.

import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { ChartService} from '../chart.service'
import * as _ from 'lodash'

@Component({
selector: 'cool-chart',
templateUrl: './cool-chart.component.html',
styleUrls: ['./cool-chart.component.scss']
})
export class CoolChartComponent implements OnInit {

@ViewChild('chart') el: ElementRef;

constructor(private chartService: ChartService) { }

ngOnInit() {
this.basicChart()
}


basicChart() {
const element = this.el.nativeElement

const data = [{
x: [1, 2, 3, 4, 5],
y: [1, 2, 4, 8, 16]
}]

const style = {
margin: { t: 0 }
}

Plotly.plot( element, data, style )
}
}

3D Topographic Chart with Firebase Data

Now let’s integrate Plot.ly with the Firebase database. For this example, our data will be only be queried once (no realtime connection).

a three dimensional topo chart in angular4 with firebase data

database structure

We have a database of arrays that correspond to the elevation of Mt Bruno in Quebec Canada. You find the original dataset here. We have a 2D array, or an Array of Arrays.

elevations
$pushKey
[number, number, ...]
[number, number, ...]

chart.service.ts

Now we need a service to handle the retrieval and updating of this data.

import { Injectable } from '@angular/core';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';



@Injectable()
export class ChartService {

constructor(private db: AngularFireDatabase) { }

getData(dataset: string) {
return this.db.list(dataset)
}


// Used for realtime data updates
updateRanking(key, newData) {
return this.db.object(`rankings/${key}`).update(newData)
}

}

updated cool-chart.component.ts

When creating the chart this time, we take one round of data, subscribe to it, then execute the topoChart() function.

Inside this function we format the data into an object, then pass some layout configuration options. Et voila, we have an amazing 3D chart in our Angular app.

/// ...omitted

ngOnInit() {
this.chartService.getData('elevations')
.take(1)
.subscribe(data => {
this.topoChart(data)
})
}



topoChart(data) {
const element = this.el.nativeElement
const formattedData = [{
z: data,
type: 'surface'
}];

const layout = {
title: 'Mt Bruno Elevation',
autosize: false,
width: 750,
height: 500,
margin: {
l: 65,
r: 50,
b: 65,
t: 90,
}
};

Plotly.plot(element, data, layout);
}

Now let’s build a chart that can handle realtime data. This type of chart shows the relationship between 3 different data properties. Imagine you have a ranking system that assigns a number between 0 and 100 to the fields of developer, designer, and analyst.

a realtime plotly chart in using the firebase realtime database

Database Structure

This time we are dealing with objects in the database, as opposed to arrays in the previous example.

rankings
$pushKey
developer: number
analyst: number
designer: number
label: string

updated cool-chart.component.ts

This time we subscribe the Firebase database and keep the subscription open. To update the chart we need to either purge it from its host element, or pass data to it with the plotly.restyle function. In this example we just purge the chart for the sake of simplicity.

ngOnInit() {
this.chartService.getData('rankings')
.subscribe(data => {
Plotly.purge(this.el.nativeElement)
this.ternaryChart(data)
})

}

updateDataPoint() {
const key = '-KrCQaF9eK1i4XcSXZUH'
const newData = {
analyst: _.random(0, 100),
designer: _.random(0, 100),
developer: _.random(0, 100)
}
this.chartService.updateRanking(key, newData)
}


ternaryChart(data) {
const element = this.el.nativeElement
const formattedData = [{
type: 'scatterternary',
mode: 'markers',
a: data.map(d => d.analyst ),
b: data.map(d => d.designer),
c: data.map(d => d.developer),
text: data.map(d => d.label),
marker: {
symbol: 100,
color: '#DB7365',
size: 14,
line: { width: 2 }
},
}]

const style = {
ternary: {
sum: 100,
aaxis: this.makeAxis('Analyst', 0),
baxis: this.makeAxis('Developer', 45),
caxis: this.makeAxis('Designer', -45),
bgcolor: '#fff1e0'
}
}

Plotly.plot(element, formattedData, style);
}


private makeAxis(title, tickangle) {
return {
title: title,
titlefont: { size: 20 },
tickangle: tickangle,
tickfont: { size: 15 },
tickcolor: 'rgba(0,0,0,0)',
ticklen: 5,
showline: true,
showgrid: true
};
}

That’s it for realtime charts with Plotly. This is only scratching the surface, so check out the documentation examples for inspiration.