R-Forge Logo

Welcome to Dynamic Time Warp project!

Comprehensive implementation of Dynamic Time Warping algorithms in R. Supports arbitrary local (eg symmetric, asymmetric, slope-limited) and global (windowing) constraints, fast native code, several plot styles, and more.

The R Package dtw provides the most complete, freely-available (GPL) implementation of Dynamic Time Warping-type (DTW) algorithms up to date.

The package is described in a companion paper, including detailed instructions and extensive background on things like multivariate matching, open-end variants for real-time use, interplay between recursion types and length normalization, history, etc.

Description

The basic DTW algorithm computes the time axis stretch which optimally maps one timeseries (query) onto another (reference); it outputs the remaining cumulative distance between the two. DTW is widely used e.g. for classification and clustering tasks in econometrics, chemometrics and general timeseries mining.

The R implementation in dtw provides:

Multivariate timeseries can be aligned with arbitrary local distance definitions, leveraging the {proxy}dist function. DTW itself becomes a distance function with the dist semantics.

In addition to computing alignments, the package provides:

Documentation

The best place to learn how to use the package (and a hopefully a decent deal of background on DTW) is the companion paper Computing and Visualizing Dynamic Time Warping Alignments in R: The dtw Package, which the Journal of Statistical Software makes available for free.

To have a look at how the dtw package is used in domains ranging from bioinformatics to chemistry to data mining, have a look at the list of citing papers.

A link to prebuilt documentation is here.

Citation

If you use dtw, do cite it in any publication reporting results obtained with this software. Please follow the directions given in citation("dtw"), i.e. cite:

Toni Giorgino (2009). Computing and Visualizing Dynamic Time Warping Alignments in R: The dtw Package. Journal of Statistical Software, 31(7), 1-24. URL www.jstatsoft.org/v31/i07/.

When using partial matching (unconstrained endpoints via the open.begin/open.end options) and/or normalization strategies, please also cite:

Paolo Tormene, Toni Giorgino, Silvana Quaglini, Mario Stefanelli (2008). Matching Incomplete Time Series with Dynamic Time Warping: An Algorithm and an Application to Post-Stroke Rehabilitation. Artificial Intelligence in Medicine, 45(1), 11-34. doi:10.1016/j.artmed.2008.11.007

Plot gallery

Go to a gallery of sample plots (straight out of the examples in the documentation).

Quickstart Example

## A noisy sine wave as query
idx<-seq(0,6.28,len=100);
query<-sin(idx)+runif(100)/10;

## A cosine is for template; sin and cos are offset by 25 samples
template<-cos(idx)

## Find the best match with the canonical recursion formula
library(dtw);
alignment<-dtw(query,template,keep=TRUE);

## Display the warping curve, i.e. the alignment curve
plot(alignment,type="threeway")

## Align and plot with the Rabiner-Juang type VI-c unsmoothed recursion
plot(
    dtw(query,template,keep=TRUE,
	step=rabinerJuangStepPattern(6,"c")),
    type="twoway",offset=-2);

## See the recursion relation, as a figure and text
plot(rabinerJuangStepPattern(6,"c"))
rabinerJuangStepPattern(6,"c")

## And much more!
Try online

Installation

To install the latest stable build of the package (hosted at CRAN), issue the following command in the R console:
> install.packages("dtw")

To get started, begin from the installed documentation:
> library(dtw)
> ?dtw
> ?plot.dtw

The development version is hosted at R-forge (project summary page):
> install.packages("dtw",repos="http://r-forge.r-project.org")

Frequently asked questions

I've discovered a multidimensional/multivariate version of the DTW algorithm! Shall it be included in the package?

Alas, most likely you haven't. DTW had been "multidimensional" since its conception. Local distances are computed between N-dimensional vectors; feature vectors have been extensively used in speech recognition since the '70s (see e.g. things like MFCC, RASTA, cepstrum, etc). Don't worry: several other people have "rediscovered" multivariate DTW already. The dtw package supports the numerous types of multi-dimensional local distances that the proxy package does, as explained in section 3.6 of the paper in JSS.

I've discovered a realtime/early detection version of the DTW algorithm!

Alas, most likely you haven't. A natural solution for real-time recognition of timeseries is "unconstrained DTW", which relaxes one or both endpoint boundary conditions. To my knowledge, the algorithm was published as early as 1978 by Rabiner, Rosenberg, and Levinson under the name UE2-1: see e.g. the mini-review in (Tormene and Giorgino, 2008). Feel also free to learn about the clever algorithms or expositions by Sakurai et al. (2007); Latecki (2007); Mori et al. (2006); Smith-Waterman (1981); Rabiner and Schmidt (1980); etc. Open-ended alignments (at one or both ends) are available in the dtw package, as described in section 3.5 of the JSS paper.

What's all the fuss about normalization? What's the problem with the symmetric1 recursion I found in Wikipedia/in another implementation?

An alignment computed with a non-normalizable step pattern has two serious drawbacks:
  1. It cannot be meaningfully normalized by timeseries length. Without normalization, longer timeseries have "naturally" higher distances, making comparisons impossible.
  2. It favors diagonal steps, therefore it is not robust: two paths differing for a small local change (eg. horizontal+vertical step rather than diagonal) have very different costs.
This is discussed in section 3.2 of the JSS paper, section 4.2 of the AIIM paper, Rabiner-Juang's book, and elsewhere. Make sure you familiarize yourself with those references. TLDR: just stick to the default symmetric2 recursion and use the normalized distance.

Can I use the DTW distance to cluster timeseries?

Of course. Arrange the timeseries (single-variate) in a matrix as rows. Make sure you use a symmetric pattern. See dtwDist.

Can I use dtwDist on timeseries of different lengths?

Either loop over the inputs yourself, or pad with NAs and use the following code:
dtwOmitNA <-function (x,y)
{
    a<-na.omit(x)
    b<-na.omit(y)
    return(dtw(a,b,distance.only=TRUE)$normalizedDistance)
}

## create a new entry in the registry with two aliases
pr_DB$set_entry(FUN = dtwOmitNA, names = c("dtwOmitNA"))

d<-dist(dataset, method = "dtwOmitNA") 

How do I deal with multiple multivariate timeseries?

You have to handle the loop yourself. Assuming you have data arranged as x[time,component,series], pseudocode would be:
 for (i in 1..N) { 
    for (j in 1..N) { 
        result[i,j] <- dtw( dist(x[,,i],x[,,j]), distance.only=T )$normalizedDistance 

Can I use dtw in Python?

Yes. See Stefan Novak's version of the quickstart example on Stack Overflow. The mapping is performed through the Python package rpy2, which makes the code natural and readable. It also plays well with numpy and multiprocessing.

What about derivative dynamic time warping?

See command diff.

License

This software is distributed under the terms of the GNU General Public License Version 2, June 1991. The terms of this license are in a file called COPYING which you should have received with this software and which can be displayed by RShowDoc("COPYING").

Contact

Toni Giorgino at gmail.com

Istituto di Ingegneria Biomedica (ISIB-CNR)
Consiglio Nazionale delle Ricerche
Padova, Italy

Academic institutions interested in a seminar or discussions are welcome to invite me. Please indicate dates, audience type and preferred length.

Commercial support

The Istituto di Ingegneria Biomedica provides on-site and remote consultancy services.






$Id: index.php 379 2014-10-29 14:14:31Z tonig $