I'll give it a shot: This solution does not create proper "legends", but merely boxed nodes, so you lose all the nice setup options. It could also probably be solved with a lot more automation (counters, looping and the like).
\documentclass{minimal}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot[label=l1]{0.1*x};
\label{p1}
\addplot{0.2*x};
\label{p2}
\addplot{0.3*x};
\label{p3}
\addplot{0.4*x};
\label{p4}
\addplot{0.5*x};
\label{p5}
\addplot{0.6*x};
\label{p6}
\end{axis}
% Draw first "Legend" node using a left justified shortstack, position using relative axis coordinates
\node [draw,fill=white] at (rel axis cs: 0.8,0.3) {\shortstack[l]{
\ref{p1} $0.1 \cdot x$ \\
\ref{p2} $0.2 \cdot x$ \\
\ref{p3} $0.3 \cdot x$}};
% Second "Legend" node
\node [draw,fill=white] at (rel axis cs: 0.3,0.8) {\shortstack[l]{
\ref{p4} $0.4 \cdot x$ \\
\ref{p5} $0.5 \cdot x$ \\
\ref{p6} $0.6 \cdot x$}};
\end{tikzpicture}
\end{document}
Well, just for fun (and to better learn new tools) I did an implementation in lua, which can be run through LuaLatex.
The lua code reads from an external .cvs
, in which data is expected to be in different lines (a number per line), and generates a tikz graphic which self-adapts its axis to the data read. Also, the generated tikz defines a set of coordinates named row1
, row2
and so on located a the center of each bar, and a coordinate named min
located at the x position of the leftmost bar. These coordinates can be used to put labels in the diagram, either centered on the bars or at the left of the graphic.
The colors used in the graphic are user-definable. If there are less colors than bars, they are cycled.
This is the LaTeX code:
\documentclass{book}
\usepackage{xcolor}
\usepackage{tikz}
\usepackage{filecontents}
\directlua{dofile("luaFunctions.lua")}
%create a pair of datafiles
\begin{filecontents*}{datafile1.csv}
2
3
2
-6
-3
\end{filecontents*}
\begin{filecontents*}{datafile2.csv}
3
4
2
3
-4
-6
2
-5
\end{filecontents*}
% latex commands to execute the lua functions
\def\waterfallChart#1{\directlua{waterfallChart("#1")}}
\def\setColors#1{%
\directlua{emptyColors()}%
\foreach \c in {#1} {\directlua{addColor("\c")}}
}
% set some styles
\tikzset{bar connection/.style = {black!50, thick}}
\setColors{cyan!80!black!50, orange, blue!80!black, red, yellow}
\begin{document}
\begin{tikzpicture} % First graph
\waterfallChart{datafile1.csv} % This draws the chart
% Now, adding labels, centered at each bar
\foreach \label [count=\n from 1] in {foo, bar, bad, foobar, spam}
\node at (row\n) {\label};
\end{tikzpicture}
\vskip 2cm
\begin{tikzpicture} % Second graph
\setColors{brown,red,orange} % Different colors for this one
\waterfallChart{datafile2.csv} % Draw the chart
% Put labels (at the left of the figure in this case)
\foreach \label [count=\n from 1] in {foo, bar, bad, foobar, spam, eggs, lorem, ipsum}
\node[left] at (row\n-|min) {\label};
\end{tikzpicture}
\end{document}
This is the result:
And this is the content of the file luaFunctions.lua
:
colors = {"blue","green"} -- Default colors
function readDataFile(filename)
local input = io.open(filename, 'r')
local dataTable = {}
local n
for line in input:lines() do
table.insert(dataTable, line)
end
input:close()
return dataTable
end
function emptyColors()
colors = {}
end
function addColor(c)
table.insert(colors,c)
end
function computeExtremes(dataTable)
local max, min, x
x = 0.0
min = 0.0
max = 0.0
for i,p in ipairs(dataTable) do
x = x + p
if (x<min) then min = x end
if (x>max) then max = x end
end
return min, max
end
function waterfallChart(filename)
local data = readDataFile(filename)
local min, max, n_steps, step, color, xpos, ypos, barwidth, aux, spread
-- Configure here as required
barwidth = 0.5 -- Height of each bar in the chart
spread = 1.4 -- Distance among baselines of the bars (in barwidth units)
n_ticks = 6 -- Number of ticks in the x-axis
min, max = computeExtremes(data)
step = (max-min)/n_ticks
max = min + n_ticks*step
xpos = 0.0
ypos = 0.0
aux = 0
-- Draw axes
-- Vertical axis
tex.print(string.format("\\draw (0,%f) -- (0, %f);",
1.1*barwidth, -#data*spread*barwidth))
-- Horizontal axis
tex.print(string.format("\\foreach \\tick in {%d, %d, ..., %d}",
min, min+step, max))
tex.print(string.format(" \\draw (\\tick, %f) -- +(0, -2mm) node[below] {\\tick};",
-#data*spread*barwidth))
tex.print(string.format("\\coordinate (min) at (%f,%f);",
min+0.0, -#data*spread*barwidth))
-- Draw the bars
color = 1
for i,p in ipairs(data) do
tex.print(string.format("\\fill[%s] (%f,%f) rectangle +(%f, %f) coordinate[midway] (row%d);",
colors[color], xpos, ypos, p+0.0, barwidth, i))
tex.print(string.format("\\draw[bar connection] (%f, %f) -- +(0,%f);",
xpos, ypos, spread*aux*barwidth))
aux = 1
ypos = ypos - spread*barwidth
xpos = xpos + 1.0 * p
color = color + 1
if (color > #colors) then color = 1; end
end
end
Best Answer
One of the most popular graphics bundles is
PGF
, which comes with a user-friedly syntax layer calledTikZ
. There are also a number of packages that all start withtkz
as a prefix. For exampletkz-2d
. You can see many examples at texampleIf these are suitable for what you are looking to produce you need to experiment and decide, although for building plans, perhaps you are better off staying with an application such as Autocad and importing pdfs in your TeX/LaTeX document.