Is there a package that provides graphing in the style of Ed Tufte?

The pgfplots package can do a lot of plotting stuff.

In contrast to the simpler sparkline package, it supports arbitrary input data - which might be given by some math expressions or table data (which might be interesting for statistical applications). It also comes with pgfplotstable which allows some automatic rounding of such tables.

In fact, I believe that I came across a solution by someone who produced pretty sparklines side-by-side using pgfplots and some table solution (looked pretty cool). If someone happens to know what I saw, this might be an interesting solution approach here (but I do not know where it is).

From my point of view, a usable solution for sparklines with pgfplots would need:

  • some styles adjustments
  • a little bit code to place start- and end nodes (together with their coordinate values)
  • a little bit math to compute min and max.

Here is the the output of an experiment this evening:

enter image description here

The source code is

% This is an experiment with a sparkline implementation based on
% pgfplots.
%
\documentclass[a4paper]{article}

\usepackage{pgfplots}


% BEGIN OF STYLE DEFINITION FOR sparkline:
\makeatletter
\usetikzlibrary{positioning}
\colorlet{sparkcolor}{red!80!black}
\colorlet{minmaxcolor}{blue!80!black}
\pgfplotsset{
    every spark line/.style={
        hide axis,
        clip=false,
        bar width=2pt,
        cycle list={blue,mark=none\\},
        height=0.8\baselineskip,
        anchor=south west,
        width=5\baselineskip,
        scale only axis,
        filter point/.code={%
            \xdef\sparklinex{\pgfkeysvalueof{/data point/x}}%
            \xdef\sparkliney{\pgfkeysvalueof{/data point/y}}%
            \pgfplotscoordmath{default}{parsenumber}{\sparklinex}%
            \let\sparklinex@=\pgfmathresult
            \pgfplotscoordmath{default}{parsenumber}{\sparkliney}%
            \let\sparkliney@=\pgfmathresult
            \ifnum\coordindex=0
                \global\let\sparklineSTARTx\sparklinex
                \global\let\sparklineSTARTy\sparkliney
                \global\let\sparklineMINx\sparklinex
                \global\let\sparklineMINy\sparkliney
                \global\let\sparklineMINy@\sparkliney@
                %
                \global\let\sparklineMAXx\sparklinex
                \global\let\sparklineMAXy\sparkliney
                \global\let\sparklineMAXy@\sparkliney@
            \else
                \pgfplotscoordmath{default}{if less than}{\sparkliney@}{\sparklineMINy@}{%
                    \global\let\sparklineMINx\sparklinex
                    \global\let\sparklineMINy\sparkliney
                    \global\let\sparklineMINy@\sparkliney@
                }{}%
                \pgfplotscoordmath{default}{if less than}{\sparklineMAXy@}{\sparkliney@}{%
                    \global\let\sparklineMAXx\sparklinex
                    \global\let\sparklineMAXy\sparkliney
                    \global\let\sparklineMAXy@\sparkliney@
                }{}%
            \fi
            \global\let\sparklineENDx\sparklinex
            \global\let\sparklineENDy\sparkliney
        },
        extra description/.code={%
            \node[begin node description]  {\pgfkeysvalueof{/pgfplots/begin node text}};
            \node[end node description]    {\pgfkeysvalueof{/pgfplots/end node text}};
        },
    },
    spark std max/.initial=,
    spark std min/.initial=,
    /tikz/spark std region/.style={fill=gray!10},
    begin node text/.initial=\pgfmathprintnumber{\sparklineSTARTy},
    end node text/.initial=  \pgfmathprintnumber{\sparklineENDy},
    /tikz/begin node description/.style={
        text width=3em,align=right,
        base left,sparkcolor,
        /pgf/number format/fixed,
        /pgf/number format/fixed zerofill,
        /pgf/number format/showpos,
        at={(current axis.south west)},
    },
    /tikz/end node description/.style={
        base right,sparkcolor,
        /pgf/number format/fixed,
        /pgf/number format/fixed zerofill,
        /pgf/number format/showpos,
        at={(current axis.south east)},
    },
    sparkline nodes/.initial={%
        node[begin node] at (axis cs:\sparklineSTARTx,\sparklineSTARTy) {}
        node[end node]   at (axis cs:\sparklineENDx,\sparklineENDy) {}
        node[min node]   at (axis cs:\sparklineMINx,\sparklineMINy) {}
        node[max node]   at (axis cs:\sparklineMAXx,\sparklineMAXy) {}
    },
    /tikz/spark marker/.style={
        circle,
        inner sep=1pt,
    },
    /tikz/begin node/.style={
        spark marker,
        fill=sparkcolor,
    },
    /tikz/end node/.style={
        spark marker,
        fill=sparkcolor,
    },
    /tikz/min node/.style={
        spark marker,
        fill=minmaxcolor,
    },
    /tikz/max node/.style={
        spark marker,
        fill=minmaxcolor,
    },
}

\def\sparkline{\pgfutil@ifnextchar[{\sparkline@opt}{\sparkline@opt[]}}%
\long\def\sparkline@opt[#1]#2;{%
    \begin{tikzpicture}[baseline]
    \begin{axis}[every spark line,#1]
        \begin{scope}[yshift=-0.2\baselineskip]
        \pgfplotsextra{
            \pgfkeysgetvalue{/pgfplots/spark std min}\sparkstdmin
            \pgfkeysgetvalue{/pgfplots/spark std max}\sparkstdmax
            \ifx\sparkstdmin\empty
            \else
                \ifx\sparkstdmax\empty
                \else
                    \fill[spark std region]
                         (axis cs:\sparklineSTARTx,\sparkstdmax) rectangle (axis cs:\sparklineENDx,\sparkstdmin);
                \fi
            \fi
        }
        \addplot #2 \pgfkeysvalueof{/pgfplots/sparkline nodes};
        \end{scope}
    \end{axis}
    \end{tikzpicture}%
}

\makeatother
% END OF STYLE DEFINITIONS

\begin{document}

\thispagestyle{empty}

\pgfplotsset{
    spark std min=-0.5,
    spark std max=0.5,
    /pgf/number format/fixed,
    /pgf/number format/fixed zerofill,
    /pgf/number format/showpos,
}

Stock A \sparkline {rand} ; 
min = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMINy}, max = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMAXy}

Stock B \sparkline {rand} ;
min = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMINy}, max = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMAXy}

Stock C \sparkline table[row sep=\\] {
x y\\
0 0\\
0.1 0.1\\
0.2 0.6\\
0.3 -0.3\\
0.4 -1.5\\
0.5 -0.4\\
0.6 0\\
};
min = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMINy}, max = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMAXy}

Stock D \sparkline[ybar,samples=15] {rand} ; 
min = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMINy}, max = \textcolor{minmaxcolor}{\pgfmathprintnumber\sparklineMAXy}
\end{document}

My idea is to define a macro \sparkline <coordinate input> ; which expects one of the different <coordinate input>s of pgfplots, as \addplot {rand}; or \addplot table (which are used above). I should note that in my case above, the space between {rand} and ; is mandatory (due to some expansion issue).

My idea is to use \baselineskip to determine the sparkline's dimensions (which, however, appears to cause problems inside of tabular!?).

The rest of the user interface is given by the options spark std min and spark std max which configure the gray background area.

Within this solution, all other things could be configured by means of styles.

See also http://pgfplots.sourceforge.net/pgfplots.pdf


I'd suggest you go with Christian Feuersänger answer but I'd also like to note that there's the path egreg mentioned in a comment.

There's the package called sparklines.

\documentclass{tufte-handout}

\usepackage{sparklines}

\begin{document}

A sparkline
\begin{sparkline}{10}
\sparkrectangle 0.3 0.8
\sparkdot 0.5 0.62 blue
\sparkdot 1 0.2 red
\spark 0.1 0.95
0.6 0.7
0.2 0.8 0.3 0.3 0.4 0.52 0.5 0.62
0.7 0.5 0.8 0.4 0.9 0.25 1 0.2 /
\end{sparkline}.
and another
\begin{sparkline}{4}
\sparkspike .083 .18
\sparkspike .25 .55
\sparkspike .417 1
\sparkspike .583 .62
\sparkspike .75 .42
\sparkspike .917 .5
\end{sparkline}.

\end{document}

Two sparklines


Although it appears that there aren't any readymade packages specifically for LaTeX, depending on which math/graphics package you use, there might be alternatives.

For example, the sagemath program provides a ready interface to LaTeX through it's sageTeX module and renders 2D plots with the Matplotlib library. Options passed on to plots that do not have meaning in Sage will be passed to Matplotlib so it is then possible to use packages like etframes to get tufte style plots. Though I only recently came across this package, I'll add more if I find them as I do research.

Tags:

Tufte

Pgfplots