Adding Graphical Context with Sparklines

Adding Graphical Context with Sparklines


You want to display a small bit of statistical contexta trend or a set of percentagesin the middle of a piece of text, without breaking up the flow of the text.


Install the sparklines gem (written by Geoffrey Grosenbach)and create a sparkline: a tiny embedded graphic that can go next to a piece of text without being too intrusive. If you're creating an HTML page, the image doesn't even need to have its own file: it can be embedded directly in the HTML.

This code creates a sparkline for a company's stock price, and embeds it in HTML after the company's stock symbol:

	require 'rubygems'
	require ' 
	require 'base64'

	def embedded_sparkline
	  %{<img src="data:image/png;base64,#{Base64.encode64(yield)}">}

	# This method scales data so that the smallest item becomes 0 and the
	# largest becomes 100.
	def scale(data)
	  min, max = data.min, data.max
	  data.collect { |x| (x - min) / (max - min) * 100}

	# Randomly generate closing prices for the past month.
	prices = [rand(10)]
	30.times { prices << prices.last + (rand - 0.5) }

	# Generate HTML containing a stock graph as an embedded sparkline.
	sparkline = embedded_sparkline { Sparklines.plot(scale(prices)) }
	open('stock.html', 'w') do |f|
	  f << "Is EvilCorp (NASDAQ:EVIL #{sparkline}) poised for a comeback?"

This code generates HTML that renders as shown in Figure.

A stock price history sparkline

Since it has no labels, the meaning of the sparkline must be determined from context. In this case, the graphic follows a stock symbol, so you can guess that it graphs the stock price. In a different context, the sparkline for EvilCorp might be the company's reported earnings over time, or the results of a poll that tracks public opinion of the company.

Embedded sparklines won't show up in Internet Explorer, but if you're using Rails you can use the sparklines_generator gem to put cross-browser sparklines in your views.


Sparklines are a way of graphically conveying information that would take lots of text to explain. They were invented by interface expert Edward Tufte, who describes them as "intense, simple, word-sized graphics." As implemented in the Ruby Sparklines library, a sparkline displays a small graph that shows a set of related numbers or a single percentage.

Sparklines are especially useful for annotating text with statistical summaries. We humans are visual creatures: when we read a text with sparklines, we come away with a better feel for the underlying numbers because we can visualize them as we read.

Sparklines are good at showing trends and making anomalies obvious. With sparklines, you can distinguish a winning sports team from a losing one at a glance, or notice an abnormally large expense report. Since neither the sparklines nor their axes are labelled, sparklines are not so good at displaying multifaceted information or absolute quantities.

Because sparklines show trends better than absolute values, it's often useful to scale your data so that it takes up the entire width of the sparkline (as in the stock price examples). But if you want to compare two sparklines to each other (for instance, to compare the stock prices of two companies), you shouldn't scale the data.

The Sparklines library can create several types of graph. Here's some code that annotates a politician's stump speech with small pie charts representing polling data. Only two colors are allowed in a sparklines pie chart: we'll choose a dark color to represent the percentage of people who agree with a statement, and a light color to represent the percentage who disagree. At a glance, the politician can see which parts of the speech are working and which need to be retooled.

	agree_percentages = [ 55, 71, 44, 55, 81, 68 ]

	speech = %{This country faces a crisis and a crossroads. %s Our taxes
	are too high %s and our poodles are too well-groomed. %s Our children
	learn less in school %s and listen to louder music at home. %s The
	Internet scares me. %s}

	open('speech.html', 'w') do |f|
	  sparklines = agree_percentages.collect do |p|
	    embedded_sparkline do
Sparklines.plot([p], :type => 'pie', :remain_color => 'pink',
	  f << speech %  

The resulting HTML file renders as shown in Figure.

A speech, annotated with poll result sparklines

The result of Sparklines.plot is a binary string containing an image in PNG format. The string can be written to a PNG file on disk, or it can be encoded with the Base64 library and embedded into a web page. The total size of speech.html, with six embedded sparklines, is about six kilobytes. Unfortunately, the Internet Explorer browser doesn't support the trick that lets you embed small images into a web page.

Sparklines in Rails Views

If you're using Rails, you can install the sparklines_generator gem on top of sparklines. This gem provides a controller and a helper that let you incorporate sparklines into your views, without having to worry about encoding the files or being incompatible with IE.

To add sparklines to your application, run this command to give yourself a sparklines controller:

	$ ./script/generate sparklines
	      create app/controllers/sparklines_controller.rb
	      create app/helpers/sparklines_helper.rb

Add a require 'sparklines' statement to your config/environment.rb file, and call helper :sparklines from any controllers in which you want to use sparklines. You can then call the sparkline_tag method from within your views.

A view that renders part of an annotated speech might look like this:

	This country faces a crisis and a crossroads.

	<%= sparkline_tag [55, 10, 10, 20, 30], :type => "pie", :remain_color=>"pink",
	:share_color => "blue", :background_color => "transparent" %>

That view generates HTML that looks like this:

	This country faces a crisis and a crossroads.

	class="sparkline" alt="Sparkline Graph" />

Instead of embedding the sparkline within the HTML page (which won't work in IE), we call out to the sparklines controller, whose only purpose is to generate image files of sparklines on demand. This image is displayed like any other external image fetched through HTTP.

See Also

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows