Sparklines

By Luke Francl (look@recursion.org)
presented at the Ruby Users of Minnesota meeting, March 28, 2006.

This is a "transcript" of my presentation as it was intended to be spoken with most of the graphics from the slides I displayed.

You may also be interested in the written text (Word, 96K), the resources sheet (Word, 42K), and the slides (PowerPoint, 150K)

"Sparkline" is a word coined by Edward Tufte to describe "small, high-resolution graphics embedded in a context of words, numbers, images." Sparklines are "word-sized graphics" which can be used to add context to data in a sentence. More than that, though, sparklines are word like graphics that can be used almost as words.

Tufte gives examples of several types of sparklines, but leaves the definition open in order to accommodate virtually any small, information-rich graphic. His definition is by necessity retroactive and he provides many examples of sparklines from previous work.

In his forthcoming book Beautiful Evidence, Tufte traces the use of word-sized graphics back hundreds of years. He gives the best example as Galileo's first description of Saturn through his telescope.

Galileo's description of Saturn
The shape of Saturn is thus as shown by perfect vision and instruments but appears thus where perfection is lacking, the shape and distinction of the three stars imperfectly seen.

Edward Tufte's Sparklines

Edward Tufte provides some examples sparklines in Beautiful Evidence.

Medical Sparkline

Medical Records. The shaded area indicates the normal range and the red number and dot indicate the latest reading.

Financial Sparkline

Mutal fund performance. The sparklines give contextual data that shows that most of these funds have virtually identical performance because they track the stock market as a whole.

baseball statistics sparkline

Baseball statistics. An entire season of games for six teams is presented as a whisker win/loss graph to give an at-a-glance summary of each team's relative performance.

Implementation in Ruby

Why's bumpspark is a limited "toy" sparkline library which can only produce one type of graph. bumpspark uses data: URIs to encode graphics and therefore requires no external libraries. It is only 11 lines of code. But because it uses data: URIs it doesn't work in Internet Explorer.

Sparklines is a more comprehensive effort by Geoffrey Grosenbach. It is a port of a Python sparklines library. The Sparklines library uses RMagick to output PNGs. Sparklines provides five types of sparklines: a pie chart (which I don't really see the point of), smooth, discrete, bar, and area. (Examples)

Using the Sparklines library

Geoffrey's Sparklines library is easy to install with the gem system.

If you don't already have the RMagick gem, install it, and then get the sparklines and sparklines_generator gems.

sudo gem install rmagick

sudo gem install sparklines

sudo gem install sparklines_generator

Once the gems are installed, run the sparklines generator to create the sparklines controller and helper files.

ruby script/generate sparklines

Then require sparklines in your environment.rb file:

require 'sparklines'

To the controller you want to use sparklines, add the helper:

class MyController < ApplicationController
  helper :sparklines
end

Now you can use the sparkline_tag helper in your view to output sparkline graphics.

Create your own sparklines with monkey patching

If the Sparklines module doesn't have the type of graphic you need, you can add it fairly easily with a little bit of RMagick programming and Ruby's facility for "monkey patching." It will then be callable from the sparkline_tag helper.

Example output from custom whisker sparkline implementation.

And the code:

require 'RMagick'
require 'sparklines'

module Sparklines

# creates a whisker sparkline to track on/off type data. There are five states: 
# on, off, no value, exceptional on, exceptional off. On values create an up 
# whisker and off values create a down whisker. Exceptional values may be 
# colored differently than regular values to indicate, for example, a shut out.
# No value produces an empty row to indicate a tie.
# 
# * results - an array of integer values between -2 and 2. -2 is exceptional 
#   down, 1 is regular down, 0 is no value, 1 is up, and 2 is exceptional up.
# * options - a hash that takes parameters
#
# :height - height of the sparkline
#
# :whisker_color - the color of regular whiskers; defaults to black
#
# :exception_color - the color of exceptional whiskers; defaults to red
  def self.whisker( results=[], options={}, maximum_value = 100.0 )
  
    height = options[:height].to_i
    whisker_color = options[:whisker_color]
    exception_color = options[:exception_color]
    
    # Set these here since they aren't in the defaults hash in the constructor
    if ( whisker_color.nil? )
      whisker_color = "black"
    end
    
    if ( exception_color.nil? )
      exception_color = "red"
    end
  
    img = Magick::Image.new( results.size * 2 - 1, height ) {
      self.background_color = options[:background_color]
    }
    img.format = "PNG"
    draw = Magick::Draw.new
    
    i = 0
    results.each do |r|
      color = whisker_color
      
      if ( (r == 2 || r == -2) && exception_color )
        color = exception_color
      end

      y_mid_point = (r >= 1) ? (img.rows/2.0 - 1).ceil : (img.rows/2.0).floor
     
      y_end_point = y_mid_point
      if ( r > 0) 
        y_end_point = 0
      end
      
      if ( r < 0 )
        y_end_point = img.rows
      end
      
      draw.stroke( color )
      draw.line( i, y_mid_point, i, y_end_point )
      i += 2
    end
     
    draw.draw(img)
    img.to_blob 
  end
end

Sparklines Resources

Edward Tufte
http://www.edwardtufte.com/tufte/

Sparklines: Theory and Practice (draft chapter from Beautiful Evidence)
http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR&topic_id=1

Bumpspark by Why
http://www.whytheluckystiff.net/bumpspark/

Sparklines by Geoffrey Grosenbach
http://nubyonrails.topfunky.com/articles/2005/07/28/sparklines-graph-library-for-ruby
http://nubyonrails.topfunky.com/articles/2005/08/01/sparklines-now-gem-i-fied
http://rubyforge.org/projects/sparklines/