# TikZ: Drawing the same data with scatter plots and parallel coordinates

I am new to TikZ and trying to recreate the following image (which was created in R): (Translation: correlation = +1, correlation = -1, two clusters, circle, normal distribution)

Each "column" displays the same data, using a scatter plot and parallel coordinates. The graphics are of course fairly simple, so it would be possible to construct them by hand with the basic \draw -- and \fill circle commands. I am however looking for the best way to create, loop through, and draw the data, kind of like it is done in the R source.

(Note: The image doesn't have to look exactly like the above, that is the number of dots does not really matter, the dots in the clusters and normal distribution can have different coordinates and it would be nice if the circle was actually round and the font was the normal font used in my LaTeX document)

-
If I'm understanding correctly these are the projections of 3D data. So if you have the data you can do this in pgfplots – percusse Sep 23 '12 at 19:20
In this example, the data is actually only 2D. – WakiMiko Sep 23 '12 at 21:18
Yes I should have said 3D plots e.g. XY plane at the bottom and YZ plane at the top – percusse Sep 23 '12 at 21:21
No, both diagrams in a column are showing the same 2 dimensions. In parallel coordinates (bottom) every point is represented as line. the X axis is at the left, the Y axis is at the right, a point is a line between both axes. – WakiMiko Sep 23 '12 at 21:52
Have a look at my answer, it's not the only way to interpret as such. – percusse Sep 24 '12 at 11:02

You can do this using PGFPlots. You can generate the x and y components for the different plots in a table, and then use them either in a normal scatterplot, or using the quiver style -- which is ordinarily used for drawing vector fields -- for the parallel plots.

\documentclass[landscape]{article}

\usepackage{pgfplots, pgfplotstable}
\begin{document}

% Create a function for generating inverse normally distributed numbers using the Box–Muller transform
\pgfmathdeclarefunction{invgauss}{2}{%
\pgfmathparse{sqrt(-2*ln(#1))*cos(deg(2*pi*#2))}%
}

% Create the data columns. \pgfplotstablerow is the row index
\pgfplotstablenew[
create on use/index/.style={
create col/expr={\pgfplotstablerow}
},
create on use/negcorr/.style={
create col/expr={24-\pgfplotstablerow}
},
create on use/clusterx/.style={ % Offset half the data by 4
create col/expr={rand+(\pgfplotstablerow<12)*4}
},
create on use/clustery/.style={
create col/expr={rand+(\pgfplotstablerow<12)*4}
},
create on use/circlex/.style={
create col/expr={cos(\pgfplotstablerow*360/24)}
},
create on use/circley/.style={
create col/expr={sin(\pgfplotstablerow*360/24)}
},
create on use/normalx/.style={
create col/expr={invgauss(rnd,rnd)}
},
create on use/normaly/.style={
create col/expr={invgauss(rnd,rnd)}
},
columns={index,negcorr,clusterx,clustery,circlex,circley,normalx,normaly}
]{24}\datatable

% Save the datatable to a file so it can be used with the quiver style
\pgfplotstablesave{\datatable}{data.csv}

% Create plot styles for the scatter and parallel plots
\pgfplotsset{
scatterplot/.style args={#1,#2}{
width=4cm, height=4cm,
only marks, mark size=1,
xtick=\empty, ytick=\empty,
enlargelimits=false,
table/x=#1,
table/y=#2
},
parallel/.style args={#1,#2}{
width=4cm, height=4cm,
no markers,
xtick=\empty, ytick=\empty,
enlargelimits=false,
table/x expr=24,
table/y=#1,
quiver={u=24,v=\thisrow{#2}-y} % The quiver plots use relative coordinates, so we'll have to subtract the y coordinate
}
}

% Create commands for making the plots easier
\newcommand{\scatterplot}[2]{
\begin{tikzpicture}[trim axis left, trim axis right]
\begin{axis}[scatterplot={#1,#2}]
\end{axis}
\end{tikzpicture}
}

\newcommand{\parallelplot}[2]{
\begin{tikzpicture}[trim axis left, trim axis right]
\begin{axis}[parallel={#1,#2}]
\end{axis}
\end{tikzpicture}
}

\scatterplot{index}{index}%
\scatterplot{index}{negcorr}%
\scatterplot{clusterx}{clustery}%
\scatterplot{circlex}{circley}%
\scatterplot{normalx}{normaly}%

\parallelplot{index}{index}%
\parallelplot{index}{negcorr}%
\parallelplot{clusterx}{clustery}%
\parallelplot{circlex}{circley}%
\parallelplot{normalx}{normaly}%

\end{document}

-
Aargh, 1 minute more .... :P – percusse Sep 23 '12 at 20:28
@percusse: Hehe, sorry! Let's see yours anyway, please! – Jake Sep 23 '12 at 20:33

Jake just went one step further and generated the data tables beautifully. So this is now obsolete as I wanted to give an example and finish off with saying This would be much better with actual data but nevermind :)

\documentclass[border=3mm]{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{groupplots}
\pgfplotsset{compat=1.6}
\begin{document}
\begin{tikzpicture}
\begin{groupplot}[group style={group size=5 by 2},view={0}{0},xtick=\empty,ytick=\empty,ztick=\empty,enlargelimits=false]
\nextgroupplot[view={90}{0}]
\pgfplotsinvokeforeach{-10,...,10}{
\addplot3[only marks] coordinates {(0,{#1},{-#1} ) (3,{#1},{-#1} )};
}
\nextgroupplot[view={90}{0}]
\pgfplotsinvokeforeach{-10,...,10}{
\addplot3[only marks] coordinates {(0,{#1},{-#1} ) (3,{-#1},{#1} )};
}
\nextgroupplot[view={90}{0},enlargelimits]
\pgfplotsinvokeforeach{1,...,15}{
}
\nextgroupplot[view={90}{0},enlargelimits]
\pgfplotsinvokeforeach{0,15,...,345}{
\addplot3[only marks] coordinates {(0,{sin(#1+5)},{cos(#1+5)} ) (3,{sin(#1+95)},{cos(#1+95)} ) };
}
\nextgroupplot[view={90}{0}]
\pgfplotsinvokeforeach{1,...,25}{
\addplot3[only marks] coordinates {(0,{5*rand},{5*rand} ) (3,{5*rand},{5*rand})};
}
\nextgroupplot
\pgfplotsinvokeforeach{-10,...,10}{
\addplot3[no marks] coordinates {(0,{#1},{-#1} ) (3,{#1},{-#1} )};
}
\nextgroupplot
\pgfplotsinvokeforeach{-10,...,10}{
\addplot3[no marks] coordinates {(0,{#1},{-#1} ) (3,{#1},{#1} )};
}
\nextgroupplot[enlarge x limits=false]
\pgfplotsinvokeforeach{1,...,15}{
}
\nextgroupplot
\pgfplotsinvokeforeach{0,15,...,345}{
\addplot3[no marks] coordinates {(0,{sin(#1+5)},{cos(#1+5)} ) (3,{sin(#1+95)},{cos(#1+95)} ) };
}
\nextgroupplot
\pgfplotsinvokeforeach{1,...,25}{
\addplot3[no marks] coordinates {(0,{5*rand},{5*rand} ) (3,{5*rand},{5*rand})};
}
\end{groupplot}
\end{tikzpicture}

\end{document}


-
Ah, interesting approach with the 3D plots! But couldn't you could achieve the same result with normal 2D ones (\addplot[only marks] coordinates {({#1},{-#1} ) ({#1},{-#1} )}; and \addplot[no marks] coordinates {(0,{#1} ) (3,{-#1} )}; for the negative correlation one, for instance)? – Jake Sep 23 '12 at 21:02
@Jake Yes you're right. But I was thinking about fixed externally provided data sets. Then you would just rotate the same plot without those rather ugly \foreach loops but your answer is just nice for those too. – percusse Sep 23 '12 at 21:15
Ah yes, good point with the external datasets! – Jake Sep 23 '12 at 21:18