Generating Encoded Values for Google’s Charts
Tuesday, December 25th, 2007Been working on some new ways of displaying various metrics. I’ve used JpGraph and PHP/SWF Charts in the past, but thought that I might invstigate some newcomers. While Sparkline PHP and Chart API / WebFX for DHTML both were interesting, I wasn’t quite able to get the libraries to do exactly what I was going for.
Google, on the other hand was able to make pretty good mix of design, customizability, flexibility and ease-of-use in their dynamic image-based Chart API.
There is one pretty big difference between Google’s Chart API and most of the other tools on the market: it won’t take raw data and automatically scale the Y-Axis to fit your data and provide labels. It instead works on a relative scale, and it is up to the developer to encode the data relatively. The library is there to help you draw your data, not actually manipulate it.
To get an idea of what I’m talking about, imagine you’re trying to build a line graph of Google’s stock price for the last five days: 689.96, 669.23, 673.35, 677.37, 689.89. Google’s Chart API has no idea what to do with these numbers–it wants to know what those numbers are relative to each other, on a scale of 0-100 (using text encoding, probably the best of the supported encoding methods).
At first glance, I suppose you could simply divide by ten in order to get a set of numbers that fits within the 0.0-100.0 space: 68.9, 66.9, 67.3, 67.7, 68.9. Problem is because the changes are relatively small between the points, you’ll end up with essentially a straight line like the graph on the right.
Not a very interesting or useful.
What you really need is something that can scale the graph so you can actual see the detail of the information. Because the stocks prices range from 669.23 to 689.96, perhaps it would make sense to make the scale from 660 to 700, which will provide adequate detail.
Scaling and adjusting the numbers relatively between 660 and 700 is a bit harder, but never fear as I wrote a little PHP function that can do it for us:
1 2 3 4 5 6 7 8 9 10 11 12 | function googleChartTextEncoding($Values,$Min,$Max) { $EncodedValues = array(); for ($i=0;$i<sizeof($Values);$i++) { $EncodedValues[] = round((($Values[$i] - $Min)/ ($Max - $Min)) * 100,1); } return(implode(",",$EncodedValues)); } $Min = 660; $Max = 700; $Values = array(689.96, 669.23, 673.35, 677.37, 689.89); $Data = googleChartTextEncoding($Values,$Min,$Max); |
This function returns values that means nothing to us as humans, but means the world to Google’s Chart API: 74.9, 23.1, 33.4, 43.4, 74.7. When we use these new scaled values, we get a graph that accurately represents the changes over the last week.
The problem is, although we’ve got the graph looking right, Google’s API also doesn’t know what metrics we’ve scaled the data on (660 to 700), so it can’t provide us with meaningful labels for the Y-Axis. Luckily I’ve got another function that can scale the labels as well:
1 2 3 4 5 6 7 8 9 | function googleChartLabels($Values,$Ticks=4,$Min,$Max){ $Spread = $Max - $Min; $Ticks = $Ticks-1; $Interval = $Spread / $Ticks; for ($t=0;$t<=$Ticks;$t++) { $Labels[] = round($Min + ($Interval * $t)); } return(implode("|",$Labels)); } |
When we put it all together:
1 2 3 4 5 6 7 8 | $Min = 660; $Max = 700; $Ticks = 4; $Values = array(689.96, 669.23, 673.35, 677.37, 689.89); $Data = googleChartTextEncoding($Values,$Min,$Max); $Labels = googleChartLabels($Values,$Ticks,$Min,$Max);?> <img src="http://chart.apis.google.com/chart?cht=lc&chs=200x100&chd=t:%3C?=$Data?%3E&chxt=x,y&chxl=0:%7C12/14%7C12/15%7C12/16%7C12/17%7C12/18%7C1:%7C%3C?=$YLabels?%3E" /> |
We get a nice-looking graph that is accurate and usable.
I suspect that Google will eventually extend the API to do all this for you, so you can just give it raw numbers and it will automatically scale the numbers and figure out the axis labels for you, much the way they eventually added GeoCoding to the Google Maps API. Until then this is a good stop-gap solution.










