Graphs 'n stuff: simple line chart with d3
Tennis: a sport almost designed for statistical analysis. You have only two primary variables (players) up against each other - whereas for something like soccer, you have 22 players who can impact the play. Much simpler - yet infinitely more complicated at the same time.
With this in mind (and with the aid of the mountains of tennis data available) I decided to trial a simple betting strategy. Simply put, it compares calculated probabilities for the outcome of tennis matches against the odds done by bookmakers. Hey, I said it was simple!
If my probabilities were more accurate than that of bookmakers, then I would make money. If they were less accurate, I would lose money.
I paper traded the strategy for a while and tracked the results. I assumed that for each bet I would put up $50. I also assumed (naively) that the odds I would get were the best available online.
The results are perfect for tracking in a line graph. So I made one!
You can find it here. It’s a line graph of my cumulative profit over time, with a cool tooltip thrown in. You’ll notice that I didn’t make much money.
However, as this is primarily a d3 post, I’ll go through that kind of stuff. Perhaps later I’ll go through my method in detail and where it fell apart.
Here are some of the things I learnt making the graph;
- The function
d3.extent()
will return the minimum and maximum of the values fed to it, and can be used to conveniently specify the domain of your axes. You can think ofd3.extent()
as callingd3.min
andd3.max
simultaneously. For example:
d3.extent(["13-01-1999","13-02-1999", "13-01-1998"]
// gives ["13-01-1998", "13-02-1999"]
- I made the tooltip entirely comprised of black writing, without a border and background. This is in contrast to the method used in the bar chart, where we implemented the package d3-tip to create a stylised tooltip containing a background.
- The problem with our tooltip sans background is that there are invariably times where it’s difficult to read. Enter: the white dropshadow - basically the text repeated in white, hidden behind the black text. This allows your black text to be easily readable at all times, and it’s easy to implement in d3!
- We can capture mouse events easily and quickly with the use of
d3.mouse()
. For example, to capture the x-position of the mouse, we can used3.mouse(this)[0]
, whiled3.mouse(this)[1]
captures the y-position. This is useful because then we can invert the position of the mouse and use bisectors to return the correct tooltip date for where our mouse is.
It turns out that you can make a nice array of basic graphs without delving into any of the animation capabilities of d3. I particularly like the tooltip functionality of this graph: we’re not repeating information that we can see already on the graph, and the blue lines allow us to easily check the values against the x and y axis.
On the other hand, creating it was significantly more complicated than using the d3-tip package. A trade-off between time and results needs to be considered. This especially applies for beginners (like myself).