What’s going on? I wanted to make clean, elegant, simple charts to represent data about armed conflicts in Africa. I used the Chart.js javascript library to obtain some pretty graphs, but I added functionality to the graphs and then wrote about it here so you can do it, too. This is the second in a series of three posts, and it’s about creating a sensible, readable scale along the x axis of a line chart.
For more info on Chart.js, have a look at the first post in this three-post series.
For looking at the data in the ACLED app, I wanted to be able to view violent events by the day, ranging back over an explicit period. The result would be a line chart:
The problem was, when I tried to make the line chart span too large of a time period, the lines would show up…but the date labels along the bottom would become too numerous, and so would get squished together on top of each other to form a thick, illegible, greyish-white bar. So in order to have any idea what sorts of time periods we were talking about, I needed the ability to show chart labels less frequent than every single day. So, maybe something like this:
This only shows the label for the first of each month. Like some of the other Chart.js hacks, this one involved a little string manipulation. In this case, the labels get passed into the chart javascript as an array. So the following code creates an array full of empty string labels except for the case of the first of the month, in which case it prints a formatted label:
That gets passed into the javascript right here (along with the raw designation, without which the empty strings were confusing the computer):
Easy. Quick. Also, clunky and kind of gross.
Later, I switched to this better implementation, which reduces the creation of @each_month to a few lines inside the controller method for yielding this page:
This uses a few new turns of syntax (it’ll catch on) to do what we want. Translated into English, it sayeth:
.map: Create an array called @each_month. For each element in the array called @days,
Date.parse(day.to_s): parse that element to a string and,
ternary operator (the ? and : line): if it is at the beginning of the month, then inject into @each_month a string with that date (specifically just the month and year), otherwise inject into @each_month an empty string.
I love learning new syntax like this (and also new ways to avoid loops, which this ternary operator kindly provides).
Reblogged this on Dinesh Ram Kali..