# Is it possible to create a barchart in a table?

I'm using booktabs to display some profiling data. I would like to add bars to each row to visually indicate the quantities in one column.

I would like to use a table instead of a barchart since there are additional columns that don't require visualisation.

Screenshot from vtune illustrating what I am looking for.

Could I maybe draw inside a cell using tikz? Or do I need to abandon the table and wrangle a pgfplots barchart to look like a table?

• just use \colorbox{\strut\hspace{1.14cm}} ... \colorbox{\strut\hspace{3.42cm}} – David Carlisle Apr 23 '14 at 13:38
• You could also format a PGFPlots plot to neatly fit into the table. Compared to David's suggestion, this has the advantage of taking care of the scaling automatically. – Jake Apr 23 '14 at 15:17

## 3 Answers

How about something like this:

\documentclass{article}
\usepackage{amsmath,amssymb}
\usepackage{array}
\usepackage{xcolor}
\def\mybar#1{%%
#1s & {\color{red}\rule{#1cm}{8pt}}}

\pagestyle{empty}
\begin{document}

\begin{tabular}{>{$\rhd$ }lrl}
Loop at line 151 in divergence  & \mybar{3.420}\\
Loop at line 1071 in radiation  & \mybar{3.270}\\
scalar face value               & \mybar{3.090}\\
Loop at line 102 in get         & \mybar{1.700}\\
get sensible enthalpy           & \mybar{1.250}\\
\end{tabular}

\end{document}


• Awesome. I ended up adding some scaling. \pgfmathsetmacro{\len}{#1*0.04} – John Apr 25 '14 at 14:09
• Where should I put \pgfmathsetmacro{\len}{#1*0.04} to add scale? – user3573959 May 14 '15 at 12:47

Example using TikZ:

\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{lmodern}

\usepackage{url}
\DeclareUrlCommand\function{\urlstyle{sf}}

\usepackage{xcolor}
\usepackage{tikz}
\usepackage{booktabs}
\usepackage{array}
\usepackage{multirow}
\usepackage{siunitx}

\definecolor{chart Idle}{gray}{.6}
\definecolor{chart Poor}{RGB}{242,28,28}
\definecolor{chart Ok}{RGB}{248,172,37}
\definecolor{chart Ideal}{RGB}{1,151,0}
\definecolor{chart Over}{RGB}{0,125,234}

\newdimen\tempdim
\newcommand*{\Triangle}{%
\settoheight{\tempdim}{L}%
\tikz[x=\tempdim, y=\tempdim]\draw(0,0) -- (.5,.5) -- (0,1) --cycle;%
}
\newcommand*{\ChartLegend}[1]{%
\ifdim\lastkern=1sp %
\hspace{1em}%
\fi
\ChartBox{0.75em}{#1}%
\,#1%
\kern-1sp\kern1sp\ignorespaces
}
\newcommand*{\ChartBox}[2]{%
\begingroup
\settoheight{\tempdim}{L}%
\edef\tempheight{\the\tempdim}%
\settodepth{\tempdim}{g}%
\edef\tempdepth{\the\tempdim}%
\tikz[
baseline=0pt,
inner sep=0pt,
]
\node[
fill={chart #2},
draw,
rounded corners=1pt,
anchor=base,
]{%
\vphantom{g\"A}%
\pgfmathsetlength{\tempdim}{#1}%
\kern\tempdim\relax
};%
\endgroup
}

\begin{document}
\sffamily
\renewcommand*{\arraystretch}{1.2}
\newcommand*{\chart}[2]{%
#1 & \ChartBox{55mm/3.420*#1}{#2}%
}
\noindent
\begin{tabular}{>{\Triangle\,}lS[mode=text,detect-family,table-format=1.3]@{\,s~}l}
\toprule
\multicolumn{1}{c}{%
\multirow{2}{*}{Source Function\,/\,Function\,/\,Call Stack}%
}&
\multicolumn{2}{c}{CPU Time by Utilization}\\
\multicolumn{1}{c}{}& \multicolumn{2}{l}{%
\ChartLegend{Idle}
\ChartLegend{Poor}
\ChartLegend{Ok}
\ChartLegend{Ideal}
\ChartLegend{Over}
}\\
\midrule
\relax[Loop at line 151 in \function{divergence_part_1}] &
\chart{3.420}{Poor} \\
\relax[Loop at line 1071 in \function{radiation_fvm}] &
\chart{3.270}{Poor} \\
\function{scalar_face_value} &
\chart{3.090}{Poor} \\
\relax[Loop at line 102 in \function{get_match}] &
\chart{1.700}{Poor} \\
\function{get_sensible_enthalpy_diff} &
\chart{1.250}{Poor} \\
\function{compare_vec3} &
\chart{1.140}{Poor} \\
\bottomrule
\end{tabular}
\end{document}


• I am utterly amazed at this faithful and beautiful reproduction. But I'm accepting the simpler solution. – John Apr 25 '14 at 14:10

Example using PGFPlots (adapted from Pgfplots: plot graph inside table) , which takes care of the scaling and lets you generate the table and graph from a datafile:

\documentclass{article}
\usepackage{booktabs}
\usepackage{multirow}
\usepackage{pgfplotstable}
\usepackage{filecontents}

% The data file
% In a real application, this would be a text file in your file system
\begin{filecontents}{data.txt}
function,cpu time
Loop at line 151,3.42
Loop at line 107,3.27
Scalar face value,3.09
Loop at line 102,1.7
Get sensible enthalpy,1.25
Compare vec3,1.14
\end{filecontents}

\pgfplotstableread[col sep=comma]{data.txt}\data

% Define the command for the plot
\newcommand{\errplot}{%
\begin{tikzpicture}[trim axis right]
\begin{axis}[y=-\baselineskip,
scale only axis,
width=5cm,
enlarge y limits={abs=0.5},
axis y line*=middle,
ytick=\empty,
axis x line*=bottom,
xbar,
bar width=1.5ex,
xmin=0,
visualization depends on=x \as \rawx,
nodes near coords,
every node near coord/.style={
anchor=east,
shift={(axis direction cs:-\rawx,0)}
}
]
%

\addplot [draw=black, fill=red]
table [x=cpu time,y expr=\coordindex]{\data};
\end{axis}
\end{tikzpicture}%
}

\begin{document}

% Get number of rows in datafile
\pgfplotstablegetrowsof{\data}
\let\numberofrows=\pgfplotsretval

% Print the table
\pgfplotstabletypeset[columns={function, cpu time},
% Booktabs rules
every head row/.style={before row=\toprule,after row=\midrule},
every last row/.style={after row=[3ex]\bottomrule},
% Set header name
columns/function/.style={string type,column type=l,column name=Function},
columns/cpu time/.style={
column name={CPU Time},
assign cell content/.code={% use \multirow for Z column:
\ifnum\pgfplotstablerow=0
\pgfkeyssetvalue{/pgfplots/table/@cell content}
{\multirow{\numberofrows}{6.5cm}{\errplot}}%
\else
\pgfkeyssetvalue{/pgfplots/table/@cell content}{}%
\fi
}
},
]{\data}
%Done!
\end{document}