2

Here's a nice simple bar graph. It's effective when the plotted values are in the same kind of ballpark, but when there's an outlier, it can put things out of wack.

For instance, I want to plot some values where:
the lowest value is 90,000,000 (90 Million);
the second highest is 500,000,000 (500 Million);
the highest value is 3,000,000,000 (3,000 Million); †3 Billion (short scale)

First of all, the bars would slide ride off the page. Even if I shift the decimal point.

Second point is, it effects the actual figures displayed on the graph.

Third point is, most of the values are towards the low end of the scale (around 100 million), so most of the bars are very small, and there is just this one massive bar. What's the solution?

enter image description here

\documentclass[margin=10, varwidth]{standalone}
\usepackage{tikz}
\tikzset{barlabels/.style={font=\footnotesize\sffamily}, declare function={barheight=5pt;}}

\begin{document}
\begin{center}
\begin{tikzpicture}[y=0.3cm, x=0.06cm]
\foreach [count=\i from 0] \p/\t in{
    10.1/Argentina,
    50.0/Armenia,
    300.0/Belgium,
    10.2/Brazil,
    10.3/Bulgaria,
    9.0/Canada,
    9.5/China,
    11.0/Taiwan,
    10.7/Czechia,
    9.9/Finland}
{\node [anchor=base east, barlabels, name=i-\i] at (0,-\i) {\t};
\fill [blue!40] (i-\i.base east) rectangle ++(\p,barheight) ++(0,-barheight) node[barlabels, black, anchor=base west] {\p};}
\end{tikzpicture}
\end{center}
\end{document}
  • 2
    How about taking the logarithm? – marmot Apr 9 at 16:09
  • @marmot Actually, that was my first thought, but I'm a bit out of my element here, I wasn't sure if that was a weird thing to do, or even how to do it, or if it would maybe even defeat the purpose of a visual representation. I'm not sure. I defer to your expertise. I actually thought maybe a pie chart would be a good way to mitigate some of the problems, but it was a bit ugly. – tjt263 Apr 9 at 16:19
  • 2
    The design of your data visualisation is really off topic here, but if the chart isn't helping (and it isn't, really) I would just tabulate the numbers. – David Carlisle Apr 9 at 16:24
  • 1
    It really depends what you want to do. You can also introduce a discontinuity symbol (see section 4.9.12 of the pgfplots manual for the meaning and usage). Or make the bars 3-dimensional such that they only scale with 3rd root of the value. – marmot Apr 9 at 16:24
  • @marmot If the logarithm method is an appropriate thing to do, I'm open to that. Can LaTeX calculate it? Or the 3-dimensional thing you said that I don't understand is probably good too. I'll take any advice I can get! :) – tjt263 Apr 9 at 16:37
2

These are two options: a discontinuity that gets inserted whenever the bar is above a user-specified cutoff and logs. It all depends on what you want to achieve. If you really just want to present the values as they are, then a table as suggested by David Carlisle may be the best.

\documentclass[margin=10,tikz]{standalone}
\usepackage{tikz}
\tikzset{barlabels/.style={font=\footnotesize\sffamily}, 
declare function={barheight=5pt;}}

\begin{document}
\begin{tikzpicture}[y=0.3cm, x=0.06cm]
\begin{scope}
\pgfmathsetmacro{\cutoff}{70}
\foreach [count=\i from 0] \p/\t in{
    10.1/Argentina,
    50.0/Armenia,
    300.0/Belgium,
    10.2/Brazil,
    10.3/Bulgaria,
    9.0/Canada,
    9.5/China,
    11.0/Taiwan,
    10.7/Czechia,
    9.9/Finland}
{\node [anchor=base east, barlabels, name=i-\i] at (0,-\i) {\t};
\ifdim\p pt<\cutoff pt
\fill [blue!40] (i-\i.base east) rectangle ++(\p,barheight) ++(0,-barheight) node[barlabels, black, anchor=base west] {\p};
\else
\fill [blue!40] (i-\i.base east) rectangle ++({\cutoff+ln(\p)},barheight) ++(0,-barheight) node[barlabels, black, anchor=base west] {\p};
\fill [white] ([xshift={((\cutoff+ln(\p))/2-1)*0.06cm}]i-\i.base east)  
to[out=45,in=-135,looseness=2] 
++(0,barheight) -- ++ (2,0) to[out=-135,in=45,looseness=2] ++(0,-barheight);
\fi}
\end{scope}
\begin{scope}[yshift=-4cm]
\foreach [count=\i from 0] \p/\t in{
    10.1/Argentina,
    50.0/Armenia,
    300.0/Belgium,
    10.2/Brazil,
    10.3/Bulgaria,
    9.0/Canada,
    9.5/China,
    11.0/Taiwan,
    10.7/Czechia,
    9.9/Finland}
{\node [anchor=base east, barlabels, name=i-\i] at (0,-\i) {\t};
\fill [blue!40] (i-\i.base east) rectangle ++({10*log10(\p)},barheight) ++(0,-barheight) node[barlabels, black, anchor=base west] {\p};
}
\end{scope}
\end{tikzpicture}
\end{document}

enter image description here

  • looks good, but can i overwrite the labels to look like 3,000,000,000 or 3 Billion, etc? – tjt263 Apr 9 at 16:54
  • 1
    @tjt263 You only need to replace node[barlabels, black, anchor=base west] {\p} by node[barlabels, black, anchor=base west] {\p~billion} or sth like that. – marmot Apr 9 at 16:58
  • I see, but then wouldn't it be 300.0 billion? I'll try it in a moment. – tjt263 Apr 9 at 17:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.