Model your data with dataseries.js

dataseries.js is a library for modeling data series with JavaScript. The main application of the library lies in generating data for prototyping, as well as assessing the robustness and edge-case behavior, of data-driven data visualizations.

The core of dataseries.js is formed from a set of data generators, each representing a particular class of data sources. As an example, there is a generator which draws data from the deterministic source of functions y = f(x), that is, functions which relate a single input value x to exactly one output value y. Additional generators to create noise or draw samples from arbitrary probability distributions are currently in the making and will be made available soon. Generators provide a convenient builder syntax which greatly facilitates the often unaesthetic process of filtering, normalizing and transforming data into custom data structures.

Let me illustrate the principle of a generator by the following example which creates a data series from the function f(x) = 2x for x in [0, 1, 2, 3]:

ds.generators.f(ds.functions.exp, { a: 2 })
    .inputs(ds.range(3))
    .values();
// => [1, 2, 4, 8]

Furthermore, the generated data can easily be transformed into a data structure that includes the provided input values and thus makes it suitable for visualizing it on a plane, e.g., via:

ds.generators.f(ds.functions.exp, { a: 2 })
    .inputs(ds.range(3))
    .transform(ds.transforms.point)
    .values();
// => [ {x: 0, y: 1}, {x: 1, y: 2}, {x: 2, y: 4}, {x: 3, y: 8} ]

By adding a time relation to the data series we effectively replace the values for x in the transformed series with suitable Date objects:

ds.generators.f(ds.functions.exp, { a: 2 })
    .inputs(ds.range(3))
    .time(new Date(2012, 0, 1), ds.time.DAY)
    .transform(ds.transforms.point)
    .values();
// => [ {x: new Date(2012, 0, 1), y: 1}, {x: new Date(2012, 0, 2), y: 2},
//         {x: new Date(2012, 0, 3), y: 4}, {x: new Date(2012, 0, 4), y: 8} ]

The goal of this article, however, is to work out a basic example on time series modeling. Most time series are composed of three components, namely: a linear trend, a repetitive seasonality component and some remainder. Consequently, such time series can be approximated by modeling these components using simple mathematical functions and a random number generator and finally superpose their outputs. But first, let us have a look at the three components in isolation:

Trend

The trend component of a time series represents a long-term movement, that is, an overall increase or a decrease of numbers in the series and is modeled using the ds.functions.linear function:
linear

Seasonality

The seasonality component identifies a seasonal variation in the series, e.g., a component which repetitively rises and falls by a weekly, monthly or yearly pattern. As a basic model we use the periodic ds.functions.sine function:
sine

Remainder

Last but not least, the remainder component adds some random fluctuation drawn from ds.random.rand:
random

Composing the Time Series

By superposing the isolated components through addition and applying some sensible scaling, we come up with the following results:
composite

for which the generator configuration looks as follows:

ds.generators.f(function(x) {
        return ds.functions.linear(x, { a: 1, b: 1 })
        + ds.functions.sin(x, { f: 0.5 })
        + ds.random.rand(-0.2, 0.2);
    })
    .inputs(ds.range(0, 1, 0.01))
    .time(new Date(2012, 0, 1), ds.time.DAY)
    .transform(ds.transforms.point)
    .values();

In this article I have shown a very basic approach to modeling time series data using dataseries.js. Checkout the complete example and API Documentation and feel free to download, fork and contribute to dataseries.js via its GitHub repository!

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>