how to create live updating and flexible d3 line charts using pseudo-data (interactive tutorial and example)

One of the bigger challenges in visualizing data is making your charts responsive so that they can resize no matter what range of data is thrown at it. Things get even more complicated when the dataset is actually a collection of many individual sets of data. One obvious example of this is a dataset containing (x,y) coordinates for multiple lines. The goal is to create a chart similar to the one below, which adapts to any new data thrown at it.

generate data

The best way to test the functionality of your graph is to generate new pseudo-data at a set interval and update the graph at the same interval. I had previously blogged about how to generate large datasets using d3 and javascript; if you are not familiar with this process, I strongly recommend that you take a quick read through that (link). For this example, we need to start by creating a function that returns a dataset comprised of (x,y) coordinates for any specified number of lines. The function below takes two arguments, the desired number of lines and the desired number of points, and returns a 2D array where each nested array is a series of (x,y) coordinates pertaining to that line. The y coordinate is multiplied by 100 to better exaggerate this example.

setup page elements

Now, we can start to setup up our page elements, such as the svg dimensions, along with the margins.

Thinking about the scales for our x and y coordinates, we can assume that our window frame is constant. It’s good practice to make these ranges dynamic based on the page dimensions, but I will gloss over it purpose of this example. The thing to keep in mind is that although our ranges are constant, our domains will change with each generation of new data, so we will leave out our range specifications for now.

create render function

Now what we must do is encapsulate the rest of the program in a function, which I have called render(), that will update our graph when a new dataset is created. When render is invoked, it first must generate a new collection of data and gather the absolute minimum and maximum in the dataset. This means that we need to loop through each set of data (i.e. line), compare the minimums and maximums amongst the other sets of data (i.e. other lines) and pull the most extreme ones of the collection. Once we have done that, we can specify the domain for our scales.

In this example, we are not drawing an x-axis and therefore are not specifying a domain for the xScale, however the process would be extremely similar if that was desired. Now that we have our scale set for this specific set of data, we can create our y-axis within our render function.

Last, we need to follow a similar process for drawing our lines:

And now, we have created our render function. All we need to do is call render and apply a setInterval on this function:

add transitions

But how do we make this graph beautifully animate and transition? First, let’s take a look at our axis. What we need to do is add a conditional statement to check to see if our scale exists. If so, all we need to do is add a transition to the new yAxis.

Now how do we update our lines? What we need to do is select all the lines currently on the page, transition them to the new line with any new attributes or styles, enter the changes in the data, and exit.

complete code

That’s it! If you’re interested in seeing the complete code, go ahead and check out my bl.ocks: http://bl.ocks.org/jonsadka/482005612916b3f5e408