Raspberry Pi Computing

Wednesday, 2 January 2013

Smoothing out the lines in d3.js

The following post is a portion of the D3 Tips and Tricks document which it free to download. To use this post in context, consider it with the others in the blog or just download the pdf and / or the examples from the downloads page:-)

--------------------------------------------------------

When you draw a line graph, what you're doing is taking two (or more) sets of coordinates and connecting them with a line (or lines). I know that sounds simplistic, but bear with me. When you connect these points, you're telling the viewer of the graph that in between the individual points, you expect the value to vary in keeping with the points that the line passes through. So in a way, you're trying to interpret the change in values that are not shown.

Now this is not strictly true for all graph types, but it does hold for a lot of line graphs.

So... when connecting these known coordinated together, you want to make the best estimate of how the values would be represented. In this respect, sometimes a straight line between points is not the best representation.

For instance. Earlier, when demonstrating the extent function for graphing we showed a graph of the varying values with the y axis showing a narrow range.

The resulting variation of the graph shows a fair amount of extremes and you could be forgiven for thinking that if this represented a smoothly flowing analog system of some kind then some of those sharp peaks and troughs would not be a true representation of how the system or figures varied.

So how should it look? Ahh... The $64,000 question. I don't know :-). You will have a better idea since you are the person who will know your data best. However, what I do know is that D3 has some tricks up its sleeve to help.

We can easily change what we see above into;

How about that? And the massive amount of code required to carry out what must be a ridiculously difficult set of calculations?

.interpolate("basis")

Now, that is slightly unfair because that's the code that YOU need to put in your script, but Mike Bostock probably had to do the mental equivalent of walking across hot coals to get it to work so nicely.

So is that it? Nooooo........ There's more! This
is one form of interpolation effect that can be applied to your data,
but there is a range and depending on your data you can select the
one that is appropriate.

Here's the list of available options and for more
about them head on over to the D3 wiki and look for 'line.interpolate'.

Because in the course of writing this I took an
opportunity to play with each of them, I was pleasantly surprised to
see some of the effects and it seems like a shame to deprive the
reader of the same joy :-). So at the risk of deforesting the planet
(so I hope you are reading this in electronic format) here is each of
the above interpolation types applied to the same data.

This is also an opportunity to add some reader feedback awesomeness. Many thanks to 'enjalot' for the great suggestion (in the comments below) to plot the points of the data as separate circles on the graphs. Since the process of interpolation has the effect of 'interpreting' the trends of the data to the extent that in some cases, the lines don't intersect the actual data much at all.

Each of the following shows the smoothing curve and the data that is used to plot the graph.

Linear

step-before

step-after

basis

basis-open

basis-closed

bundle

cardinal

cardinal-open

cardinal-closed

monotone

So, over to you to decide which format of
interpolation is going to suit your data best:-).

The above description (and heaps of other stuff) is in the D3 Tips and Tricks document that can be accessed from the downloads page of d3noob.org.

Hey, this is great!It would be really helpful if you also plotted the points of the data as circles so that it was readily apparent that some of these interpolations do not accurately represent the data.thanks again!

Cool! Done. I figured you wouldn't mind me giving you credit by name (enjalot) in the text. If you'd rather not, just let me know. I've also updated the book. (https://leanpub.com/D3-Tips-and-Tricks). Many thanks. Great suggestion. I don't think I've seen this illustrated this way before.

Ahh... Interesting question.Yes it is.All you need to do is add in an additional block like the 'var valueline = blah bal blah...' but name it something different (like valueline2) and then add another block that adds the valueline2 path. That way you have two different paths and you can change the interpolations on either to suit. Thanks for the question

Thanks. But I don't quite get what you mean. The captions on the graphs above are correct and they appear to be in the same order as the description. I just ran a quick test to make sure that the steps actually do go in the direction that I thought they did so I'm a bit flummoxed. Could you describe the problem in a slightly different way? Thanks for the feedback.

Hello, i would like to ask that how can i find local max and local min values and also if there is a plateau ? I have a graph to measure tension according to values. I have to check for bumps if exist ? Thank you for your interest.

Good question. There will obviously be a bit of work involved here. I assume that we are looking for a way to find areas where the change in gradient means the line that is tangent to the curve changes relative to points before and after it. I have never played with this before, but the following pages may be of use; http://www.thesoftwaresimpleton.com/blog/2016/01/26/tangent/, http://www.d3geometry.com/functions?uid=8888, https://bl.ocks.org/andresin87/4c5a34136c9a543d68de