Recurrence Plot and Cross Recurrence Plot for Data Science Visualization and Analysis

Daniel de Souza Carvalho, Wolfram Research

(RowDefault[, (Spacer1), , (Spacer1), ])  #WolframTechConf

ABSTRACT

Recurrence plots are powerful advanced tools for visualizing and analyzing complex data in time-series and data sciences. The data can be seen into a 2D space, revealing patterns, trends, and recurrences that may be hidden in the original sequential graphic formats. Lets explore interactive cases.

Format: Talk
Focus areas: Data Science, Graphics & Visualization

Contact: dcarvalho@wolfram.com

Define Recurrence Plots

Synthesizing some AI aid descriptions

Briefly, recurrence plots are useful to visualize patterns in numerical sequential vector (list) data, for descriptive statistics, dynamical systems and chaos theory. We can observe randomness, repeating, clusters, periodicity, and random motion in a reticulated 2D graphic (binary square matrix - list of lists), we can see the states in data over time.

First case: Cross-recurrence plot of two different random integer vector with integer numbers from 0 to 9, one at x-axis and another at y-axis:

ResourceFunction["CrossRecurrencePlot"][
RandomInteger[9,30],
RandomInteger[9,30],Mesh-> True]

Definition:

"Recurrence plot – A recurrence plot (RP) is an advanced technique of nonlinear data analysis. It is a visualisation (or a graph) of a square matrix, in which the matrix elements correspond to those times at which a state of a dynamical system recurs (columns and rows correspond then to a certain pair of times). Techniqually, the RP reveals all the times when the phase space trajectory of the dynamical system visits roughly the same area in the phase space."

Source: http://www.recurrence-plot.tk/glance.php

With a little help from LLM GPT-4 lets describe what a recurrence plot means (AI aid explanation highlighted in orange)

llmContent[prompt_]:=CellPrint[Cell[LLMSynthesize[prompt],"Text",Orange]];

llmContent["In a paragraph define recurrence plot graphic"]

A recurrence plot is a graphical tool used to visualize the recurring patterns and dynamics of a system over time. It provides a way to represent the times at which a state of a dynamical system recurs, based on the properties of its phase space trajectory. Typically, in a two-dimensional square matrix, both axes represent the same temporal sequence, and dots are placed at locations where a particular state recurs. This matrix is symmetric, with a diagonal line from the bottom-left to the top-right representing the line of identity, where each point is compared to itself. The recurrence plot can reveal information about the periodicity, stability, and underlying structure of the system, making it particularly useful in fields such as time-series analysis, system dynamics, and chaos theory. Its ability to uncover non-linear patterns makes it a powerful tool for identifying complex, hidden behaviors within data.

Another AI aid explanation for Recurrence Plots, summary combining both Wikipedia and Math World texts:

Style[TextSummarize[StringJoin[{
Import["https://mathworld.wolfram.com/RecurrencePlot.html"],
"\n\n" ,
WikipediaData["Recurrence plot"]}]],Orange]

Recurrence Plot Patterns

How to read the data visualization

It is possible to observe and analyze four main patterns at the binary reticular:

"Characteristic typology of recurrence plots: 

(A) homogeneous (uniformly distributed noise),
(B) periodic (super-positioned harmonic oscillations), 
(C) drift (logistic map corrupted with a linearly increasing term) and 
(D) disrupted (Brownian motion). 

These examples illustrate how different RPs can be. The used data have the length 400 (A, B, D) and 150 (C), respectively; no embeddings are used; the thresholds are ε = 0.2 (A, C, D) and ε = 0.4 (B)."

Source: 
http://www.recurrence-plot.tk/glance.php
https://en.wikipedia.org/wiki/Recurrence_plot

Example 1 - math

Comparing trigonometrical functions interactively

The Cross-recurrence plot compars two distinct discrite signals (numerical vectors, float or integer) by the x-axis and y-axis in a binary matrix, where a point is marked if the state of the system at two different times is close enough according to a pre-defined threshold ε.

We can compare sine (x-axis) and cosine (y-axis) time series pattern:

Manipulate[Grid[{{
ListPlot[tsin,Filling->Axis,PlotLabel->"Sine"],
ListPlot[tcos,Filling->Axis,PlotLabel->"Cosine"]},{
ResourceFunction["CrossRecurrencePlot"][
tsin=Table[Sin[fsin x],{x,-size,size}],
tcos=Table[Cos[fcos y],{y,-size,size}],Mesh->grid,ColorRules->{0->Yellow, 1->Orange}],SpanFromLeft}}],
{fsin,1,10,.1},
{fcos,1,10,.1},
{size,10,100,1},
{{grid,True},{True, None}}]

Example 2 - computing

Comparing two simple lists

The recurrence plot applys the same discrite signal (numerical vectors, float or integer) by the x-axis and y-axis in a binary matrix.

Both functions RecurrencePlot and CrossRecurrencePlot supports ArrayPlot parameters.

Recurrence plot of a integer vector with numbers from 0 to 9.
The same vector (list) are used in the x-axis and y-axis to create the recurrence matrix (list of lists) and have it plotted:

ResourceFunction["RecurrencePlot"][RandomInteger[9,30],Mesh->All]

As we are using the same vector (list) for x-axis and y-axis, there are recurrence at the diagonal line.

To illustrate the concept, here we have a cross-recurrence plot of two different integer small vectors, with some values from 1 to 200:

ResourceFunction["CrossRecurrencePlot"][
{1,10,20,100,200,200,200,100,20,10,2},
{3,12,19,130,200,200,201,100,20,10,2}]

There is a ε threshold distance we can adjust:

Manipulate[ResourceFunction["CrossRecurrencePlot"][
{1,10,20,100,200,200,200,100,20,10,2},
{3,12,19,130,200,200,201,100,20,10,2},"RecurrenceThreshold"->ε,Mesh->True],
{ε,.1,5}]

This is the same data, but with global cross-recurrence plot (unthresholded), that shows the intermediate diference values, instead of a binary matrix with the closest cases:

ResourceFunction["CrossRecurrencePlot"][
{1,10,20,100,200,200,200,100,20,10,2},
{3,12,19,130,200,200,201,100,20,10,2},
RecurrenceType->"Global"]

This other case we are using range from 0 to 10 at both x-axis and y-axis of a global cross-recurrence plot (unthresholded):

ResourceFunction["CrossRecurrencePlot"][
Range[10],
Range[10],
RecurrenceType->"Global"]

This other case we are using again the range from 0 to 10 at both x-axis and y-axis, but now with a global recurrence plot :

ResourceFunction["RecurrencePlot"][
Range[10],
RecurrenceType->"Global"]

Both two cases rises up equal patterns.

Bellow we have the same data and plot, but in color for better visualization:

ResourceFunction["RecurrencePlot"][
Range[10],
RecurrenceType->"Global",
ColorFunction->Hue]

Cross-recurrence visualization to compair two random vectors:

ResourceFunction["CrossRecurrencePlot"][
RandomInteger[10,100],
RandomInteger[10,100],ColorRules->{0-> Yellow, 1-> Orange},Frame-> None]

Example 3 - math again

More using trigonometrical functions

We have a trigonometric product of Sine and Cosine functions, where we can vary the frequency, etc... by a Manipulate interactive function:

Manipulate[GraphicsGrid[{{ListLinePlot[{
s1=Table[Sin[x f1x]*Cos[x f1y],{x,-10,10,size}],s2=Table[Sin[y f2x]*Cos[y f2y],{y,-10,10,size}]}],ResourceFunction["CrossRecurrencePlot"][s1,s2,Frame->None]}}],
{f1x,1,10},
{f1y,1,10},
{{f2x,5},1,10},
{{f2y,7},1,10},
{size,.1,2.}]

Example 4 - NKS - computer science

Comparing two ECA (Elementary Cellular Automata) computational models

Using random initial condition for the ECAs:

Manipulate[SeedRandom[92177];
init=RandomInteger[1,100];
GraphicsGrid[{{
Row[{"ECA rule # ",rule1}],
Row[{"ECA rule # ",rule2}]},
{RulePlot[CellularAutomaton[rule1]],RulePlot[CellularAutomaton[rule2]]},{
ArrayPlot[ca1=CellularAutomaton[rule1,Take[init,size],size],Frame->None],
ArrayPlot[ca2=CellularAutomaton[rule2,Take[init,size],size],Frame->None]},{
ListLinePlot[{ca1dynamics=Total[Transpose[ca1]],ca2dynamics=Total[Transpose[ca2]]}],ResourceFunction["CrossRecurrencePlot"][ca1dynamics,ca2dynamics,Frame->None,RecurrenceType->"Global",ColorFunction->Hue]}}],
{{rule1,30},0,255,1},
{{rule2,110},0,255,1},
{{size,50},10,100,1}]

To learn more about ECA:
https://www.wolframscience.com/nks/

Example 5 - data science

Flower Data

Fisher’s Irises botanic research data, a classic for Data Science education.

Importing data from Wolfram Data Repository as a Dataset data structure (data frame):
https://datarepository.wolframcloud.com/

irisFlower = ResourceData[ResourceObject["Sample Data: Fisher's Irises"]]

We need to convert categorical data (text) to numerical:

irisFlower[GroupBy["Species"]]

We will use this association (key pair data structure) to create a new column at the Dataset:

species=<|
"setosa"->1,
"versicolor"->2,
"virginica"->3|>;

Testing the association:

species["setosa"]

Creating a new column at the Iris Dataset:

irisFlower = irisFlower[All,<|#,"SpeciesNumerical"->species[#Species]|>&]

Cleaning the data, moving to a simple numerical vector from a Dataset:

irisCleaned=Rest/@ Normal[QuantityMagnitude[Values[irisFlower]]];

Check data dimensions:

Dimensions[irisCleaned]

View the top of the data, now all in a simples list as numbers (integer or float), instead of a data frame (Dataset):

Shallow[irisCleaned]

Visualize the Recurrence Plot:

ResourceFunction["RecurrencePlot"][irisCleaned]

Visualize the global recurrence plot (unthresholded):

ResourceFunction["RecurrencePlot"][irisCleaned,RecurrenceType->"Global",ColorFunction->"Rainbow"]

Example 6 - financing

USD ($) vs EUR (€)

Time series data
Using exchange 2023

Load financial computable data from Wolfram|Alpha:

rates=TimeSeries[First[WolframAlpha["euro to dollar in 2023",{{"Result",1},"ComputableData"}]]];

The data is in a time series format (data structure):

rates

We have all 2023 daily rates:

First[rates["Values"]]

Now getting just the exchange value by day, just a simple numerical vector (list):

ratesValues=QuantityMagnitude[rates["Values"]];

Checking the top of the list, floats representing the ratio USD vs EUR:

Shallow[ratesValues]

Checking the size, it is 255 of course:

Length[ratesValues]

Recurrence plot pattern visualization:

ResourceFunction["RecurrencePlot"][ratesValues]

Global recurrence plot visualization (unthresholded):

ResourceFunction["RecurrencePlot"][ratesValues,RecurrenceType->"Global",ColorFunction->"Rainbow"]

Implementation

RecurrencePlot and CrossRecurrencePlot at Wolfram Function Repository

Both functions implementations uses the same equation:

Where i on a horizontal axis and j on a vertical axis, and (Overscript[x, ->]) is the state of the system, or its phase space trajectory, in time.

Source: 
http://www.recurrence-plot.tk/glance.php
https://mathworld.wolfram.com/RecurrencePlot.html

The implementation is very straight forward, because Wolfram Language has all the building blocks (functions) ready to go.

Combining two numerical vectors (list) as input to create and visualize the 2D recurrence matrix (list of lists) as output:

...
ArrayPlot[Table[
If[recurrenceType==="Global",#,
UnitStep[#]]&[ϵ-Norm[i[[x]]-j[[y]]]],
{x,1,Length[i],1},
{y,1,Length[j],1} ]]
...

Wolfram Language documentation make it easy to go from equation to code: https://reference.wolfram.com/language/

?UnitStep

?Norm

?ArrayPlot

Final Thoughts

Functions future advancements

Recurrence plots are interesting for data science and analysis because they reveal underlying patterns and dynamics in complex systems, time series and data, especially in detecting periodicity, chaos, randomness, and state recurrence.

For convenience, future versions of RecurrencePlot and CrossRecurrencePlot can implement support for Dataset, time series, and association (data structures) as input, automatic categorical data to numerical conversion, and automatic data cleanup.

References:

Recurrence plot implementations and bibliography.

Carvalho, D. S., “RecurrencePlot | Wolfram Function Repository”, 2014.
https://resources.wolframcloud.com/FunctionRepository/resources/RecurrencePlot

Carvalho, D. S., “CrossRecurrencePlot | Wolfram Function Repository”, 2019.
https://resources.wolframcloud.com/FunctionRepository/resources/CrossRecurrencePlot/

Recurrence Plots and Cross Recurrence Plots, 2024.
http://www.recurrence-plot.tk

Recurrence plot | Wikipedia, 2024.
https://en.wikipedia.org/wiki/Recurrence_plot

E. W. Weisstein, “Recurrence Plot.” From MathWorld - A Wolfram Web Resource (2014). https://mathworld.wolfram.com/RecurrencePlot.html

N. Marwan, M. C. Romano, M. Thiel, J. Kurths, “Recurrence Plots for the Analysis of Complex Systems”, Physics Reports, 438(5-6), 237-32, 2006.
DOI: 10.1016/j.physrep.2006.11.001