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}]
\addplot [black] table {data.csv};
\end{axis}
\end{tikzpicture}
}
\newcommand{\parallelplot}[2]{
\begin{tikzpicture}[trim axis left, trim axis right]
\begin{axis}[parallel={#1,#2}]
\addplot [black] table {data.csv};
\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}
You can use the /.list
handler.
\tikzset{myrowstyle/.style = {row #1/.style={nodes={fill=gray!10}}}
and later in the picture you can then use
myrowstyle/.list={1,...,10}
or any other argument list.
Best Answer
One way of doing this is using leaders:
The general format for constructing leaders is
\leaders<box or rule><glue>
(which repeats<box or rule>
). There are three kinds of leaders that you can use:\leaders
,\cleaders
and\xleaders
. Here is an informal description of each, taken from The Advanced TeXBook:Here, and just for fun, the difference between using
\kitty
with\leaders
,\cleaders
and\xleaders
:Also see the TeXBook for reference (chapter 21 Making Boxes, p 223):