GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||
GeezerVison is showing wiretrip.github.io — StreamGraph A while ago at work we had a need to display changing ‘share of voice’ or ‘contribution of themes’ information over time. Essentially this would mean displaying the ‘Top 1 themes’ or ‘Top 1 authors’ for each epoch or timespan. The same authors and themes would typically exist in multiple epochs, but not necessarily contiguously; authors/themes could appear for a few epochs, disappear again and then reapppear later on, and new themes could appear at any point. But for this fact, a stacked area graph or a classic stream graph would work perfectly. Some WWW research, however, soon revealed this lovely graph. It is able to show the proportional sizes of the entities in each epoch, their changes in ‘rank’, and allows for entities to ‘join’ and leave, starting and ending streams over their lifetimes. Unfortunately, no source was available and I was unable to find any implementations at all. The only option was to do it myself, the results of which are here. To keep things simple, and instantly useful, there were three constraints:
The library code is here and there is a working example at the end of the post. How it works1. Organise the dataThe first stage of processing is to fetch the graph’s data - this arrives a json in the following format:
Each object represents a count of items of a particular category or series (‘partition’) and at a particular point in time (‘date’ : number of milliseconds since 01/01/1970). We use jquery to fetch the data and then we ‘bin’ the items into particular epochs (we do this by converting the ‘date’ value into a sortable string representation, e.g. ‘2015/06/05’ and adding the items to a ‘StreamColumn’ object representing that date).
Note that when we add an ‘item’ to a column, we add it as an object ‘keyed’ on the ‘partition id’ to allow us to access the items by partitionId.
By now we have all the data placed into ‘date’ columns. Optionally, at this point we can fill in some of the blanks, either by insisting that each column ‘stack’ contains all of the partitions/series and adding 0 scored items where they are not already there, or by ‘bridging’ series across columns with missing values as below:
We do this by looking at each series in a stack, checking to see if it is in the previous column, and if not, we check the column before that, if it is in that ‘previous-previous column’, then we add a 0 scoring item of that series to the previous column.
2. Prepare the layoutFirst we sort the columns into date order ( by sorting our ‘map’ of StreamColumns by the date/column label ). Next we sort each stack into descending score order (we could optionally sort by series name - which would give us a stacked area graph essentially). Finally, we iterate through each column and mark out a stack of rectangles, where the width is defined in ‘columnWidth’ and the height is the score * yScale. The yScale can be decided in two ways
3. Draw the graphFinally, we draw the graph using SVG tags. Essentially we draw a stack of rectangles but with a twist: for each item, we check to see if there is an item of the same series in the previous column, if there isn’t, we draw a simple rectangle. If there is however, we draw the a path that starts at the top-right corner of the previous rectangle and follows a Bezier curve to the top left of this item rectangle, following round the rectangle and then back via a bezier curve to the bottom right of the previous rectangle. This creates a nice join between the two columns.
Example - Temperatures in 2015 in major UK cities.The HTML is here, the Javascript is here and the data JSON is here. StravaWeatherA project to add weather information to Strava activities. Continue reading DeXtreePublished on April 15, 2014 | ||||||||||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |