Welcome to the first chapter of ‘A Complete Data Visualization Course’ on Spatio-temporal visualization.

Spatio Temporal Visualization

Introduction

A Spatio-temporal visualization is a type of visualization that is best suited for data having features of both space and time along with a focus feature. Such kind of data is also known as Spatio-temporal data.

  • Space Feature – A space feature indicates the location of a point/points in an n-dimensional space. For example, (40.7128° N, 74.0060° W) is a 2-dimensional space feature that represents the latitude and longitude of New York City.
  • Time Feature – A time feature indicates a particular instant of time. For example, 2010 AD, 2:00 AM, etc. is a time feature that represents a particular instant of time.
  • Focus Feature – A focus feature indicates a piece of insightful information that is often kept in the focus of the audience. For example, amount of rainfall, temperature, number of sales, etc. are focus features.

The following Spatio-temporal visualization by OpenGeoHub is a perfect example for demonstrating the space and time feature along with ‘Population in millions’ as a focus feature.

Industrial Use Cases of Spatio-Temporal Visualizations

Two of the most important use cases for Spatio-temporal visualizations are as follows:

  1. Location Tracking and Analysis – Ridesharing and Delivery companies use Spatio-temporal visualization to track the real-time position of objects, vehicles, etc. by plotting the object’s GPS coordinates on a map that changes with respect to time.
  2. Statistical Analysis – Most businesses use Spatio-temporal visualizations for analyzing and presenting Spatio-temporal data as a part of their business process. Environmental activists are also seen to heavily rely on Spatio-temporal visualizations for raising awareness about various environmental changes such as deforestation, global warming, etc.

Getting Started With Spatio-Temporal Visualization

Spatio-Temporal visualizations are being used mostly everywhere and thus, new techniques for creating such visualizations are being researched heavily on a day-to-day basis.

Uber, a ride-sharing company, has become one of the major names in the field of Spatio-temporal visualization research ever since the release of their open-source Spatio-temporal visualization library called deck.gl on Jan 6, 2016.

Deck GL - The Click Reader

deck.gl is a WebGL-powered framework for visual exploratory data analysis of large datasets with up to 64-bit floating-point computations in the GPU. It is a very powerful tool for building Spatio-temporal visualizations from scratch. The library provides a layered approach to data visualization and allows complex visualizations to be constructed using pre-existing layers.

It also allows seamless integrations with React and Mapbox which means that you will have no problem integrating deck.gl into your existing React apps.

To learn how to build powerful web visualizations using deck.gl, we recommend viewing the tutorials at the Vis Academy. Vis Academy features tutorials and classes prepared by the Uber Visualization team.

First Step: Set up your coding environment

Set up your coding environment using Vis Academy’s guides.

Second Step: Create a map using MapboxGL

Time to create a map to display your data on. If you have already got your Mapbox token by following the first step, you will have no problem creating a map using MapboxGL.

Here is a guide showing you how to create a map using MapboxGL by the Vis Academy: Starting with a Map

Mapbox

The final code for creating the app.js file is as follows:

/* global window */
import React, { Component } from 'react';
import MapGL from 'react-map-gl';
import {MapStylePicker} from './controls';

export default class App extends Component {
  state = {
    style: 'mapbox://styles/mapbox/light-v9',
    viewport: {
      width: window.innerWidth,
      height: window.innerHeight,
      longitude: -74,
      latitude: 40.7,
      zoom: 11,
      maxZoom: 16
    }
  }

  componentDidMount() {
    window.addEventListener('resize', this._resize);
    this._resize();
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this._resize);
  }

  onStyleChange = (style) => {
    this.setState({style});
  }

  _onViewportChange = (viewport) => {
    this.setState({
      viewport: { ...this.state.viewport, ...viewport }
    });
  }

  _resize = () => {
    this._onViewportChange({
      width: window.innerWidth,
      height: window.innerHeight
    });
  }

  render() {
    return (
      <div>
        <MapStylePicker onStyleChange={this.onStyleChange} currentStyle={this.state.style}/>
        <MapGL
          {...this.state.viewport}
          mapStyle={this.state.style}
          onViewportChange={viewport => this._onViewportChange(viewport)}
        >
        </MapGL>
      </div>
    );
  }
}

Second step: Add data onto the map

Once your map is ready, you are now ready to add data onto the map. How you want to display your data onto the map is wholly your choice and here is a list of all data overlays that you can plot onto the map.

  • Scatterplot
  • Arc
  • Geojson: Path
  • Geojson: Chorepleth
  • Hexagon
  • 3D Hexagon

The following tutorial by Vis academy uses data from NYC taxi rides to plot data as a scatterplot tutorial showing you how to plot your data using scatterplots: Map data overlays – Scatterplot. The tutorial uses data from NYC taxi rides but you can use your own data as needed.

Scatter plot - The Click Reader

The final code for creating the app.js file is as follows:

/* global window */
import React, { Component } from 'react';
import { StaticMap } from 'react-map-gl';
import {
  LayerControls,
  MapStylePicker,
  SCATTERPLOT_CONTROLS
} from './controls';
import { tooltipStyle } from './style';
import DeckGL from 'deck.gl';
import taxiData from '../../../data/taxi';
import { renderLayers } from './deckgl-layers';

const INITIAL_VIEW_STATE = {
  longitude: -74,
  latitude: 40.7,
  zoom: 11,
  minZoom: 5,
  maxZoom: 16,
  pitch: 0,
  bearing: 0
};

export default class App extends Component {
  state = {
    hover: {
      x: 0,
      y: 0,
      hoveredObject: null
    },
    points: [],
    settings: Object.keys(SCATTERPLOT_CONTROLS).reduce(
      (accu, key) => ({
        ...accu,
        [key]: SCATTERPLOT_CONTROLS[key].value
      }),
      {}
    ),
    style: 'mapbox://styles/mapbox/light-v9'
  };

  componentDidMount() {
    this._processData();
  }

  _processData = () => {
    const points = taxiData.reduce((accu, curr) => {
      accu.push({
        position: [Number(curr.pickup_longitude), Number(curr.pickup_latitude)],
        pickup: true
      });

      accu.push({
        position: [
          Number(curr.dropoff_longitude),
          Number(curr.dropoff_latitude)
        ],
        pickup: false
      });
      return accu;
    }, []);
    this.setState({
      points
    });
  };

  _onHover({ x, y, object }) {
    const label = object ? (object.pickup ? 'Pickup' : 'Dropoff') : null;

    this.setState({ hover: { x, y, hoveredObject: object, label } });
  }

  onStyleChange = style => {
    this.setState({ style });
  };

  _updateLayerSettings(settings) {
    this.setState({ settings });
  }

  render() {
    const data = this.state.points;
    if (!data.length) {
      return null;
    }
    const { hover, settings } = this.state;
    return (
      <div>
        {hover.hoveredObject && (
          <div
            style={{
              ...tooltipStyle,
              transform: `translate(${hover.x}px, ${hover.y}px)`
            }}
          >
            <div>{hover.label}</div>
          </div>
        )}
        <MapStylePicker
          onStyleChange={this.onStyleChange}
          currentStyle={this.state.style}
        />
        <LayerControls
          settings={this.state.settings}
          propTypes={SCATTERPLOT_CONTROLS}
          onChange={settings => this._updateLayerSettings(settings)}
        />
        <DeckGL
          layers={renderLayers({
            data: this.state.points,
            onHover: hover => this._onHover(hover),
            settings: this.state.settings
          })}
          initialViewState={INITIAL_VIEW_STATE}
          controller
        >
          <StaticMap mapStyle={this.state.style} />
        </DeckGL>
      </div>
    );
  }
}

The final code for creating the deckgl-layers.js file is as follows:

import { ScatterplotLayer } from 'deck.gl';

const PICKUP_COLOR = [0, 128, 255];
const DROPOFF_COLOR = [255, 0, 128];

export function renderLayers(props) {
  const {data, onHover, settings} = props;
  return [
    settings.showScatterplot && new ScatterplotLayer({
      id: 'scatterplot',
      getPosition: d => d.position,
      getColor: d => (d.pickup ? PICKUP_COLOR : DROPOFF_COLOR),
      getRadius: d => 5,
      opacity: 0.5,
      pickable: true,
      radiusMinPixels: 0.25,
      radiusMaxPixels: 30,
      data,
      onHover,
      ...settings
    })
  ];
}

There you have it.

Example visualizations that you can make using deck.gl

  1. Autonomy Visualization System – A visualization protocol and toolkit for robotics data in the browser.

2. Singapore Bus Routes Explorer – Explore bus stops and routes on the map for all bus services in Singapore with realtime bus arrival times and per-bus-stop passing routes overview.

Singapore Bus Routes Explorer

3. Kepler.gl – Kepler.gl is a powerful web-based geospatial data analysis tool which is built on a high-performance rendering engine and is designed for large-scale data sets.

4. The Bad Bet – Data journalists use deck.gl to visualize how the revenue generated by video gambling machines in Illinois grow over time and how those revenues failed to meet the projections of legislators.

These are only some of the example capabilities of deck.gl. You can view other examples from here.

In Conclusion

We hope that this first chapter from ‘A Complete Data Visualization Course‘ helps you get started on creating amazing and meaningful Spatio-temporal visualizations.

Move onwards to ‘Chapter II: Automotive Visualization‘ to continue learning.

Also, if you have any questions, please feel free to let us know in the comment section.

LEAVE A REPLY

Please enter your comment!
Please enter your name here