4

The bar chart below is what I have at the moment. As you see there is a huge difference between the y-values. I could use a logarithmic x-axis, but this is not readable for non-scientists.

I want to make the x-area between 0 and 500 twice as big and the rest shrinks accordingly. How do I change the distribution on an axis?

I hope you understand what I mean, it is difficult for me to explain it.

plot

edit: I tried to apply the answer of this question Axis break in pgfplots but unfortunatelly i wasn't able to do it with bar charts.

\documentclass[]{article}

\usepackage{pgfplots}
\usepackage{pgfplotstable}

\begin{document}

\title{Title}
\author{Author}
\date{Today}
\maketitle

\pgfplotsset{width=15cm, compat=4}

\begin{tikzpicture}
    \begin{axis}[xbar stacked, nodes near coords,
                xbar=30pt,
                bar width=5,
                xmajorgrids = true,
                yticklabel style={/pgf/number format/1000 sep=,font=\tiny},  
                ytick=data,
                bar width= .2cm,
                    nodes near coords align = {horizontal},
                        nodes near coords,
                        nodes near coords align=right,
                        every node near coord/.style={color=black,font=\tiny}
              ]

        \addplot[draw=green,fill=green!50,enlargelimits=0.25]
            coordinates{
                  (3133,1)  (731,2)  (1196,3)  (273,4)  (83,5)  (312,6)  (40,7)  (36,8)  (76,9)  (15,10)  (8,11)  (38,12)  (9,13)  (7,14)  (20,15)  (3,16)  (2,17)  (13,18)
                  (2,19)  (4,20)  (3,21)  (2,22)  (2,23)  (2,24)  (1,26)  (1,27)  (1,28)  (1,30)  (2,31)  (2,33)  (1,35)  (1,36) 
            };
    \end{axis}
\end{tikzpicture}

\end{document}

2 Answers2

9

A word of warning: Don't do this, it's extremely confusing for the reader. Displaying the data like this completely distorts the relationship between the data points. What reason is there for compressing the range above 500? At the extreme, you could ask for all ranges to be compressed in such a manner that you end up with 36 equally sized bars that just have different numbers at their end. What purpose does that serve?

That said, if you really want to go ahead with this, you can use the x coord trafo and x coord inv trafo functionality to transform the data. Note that you need to use point meta=rawx to display the original values at the bar ends, and you should manually specify the tick positions using xtick={0,500, ... }:

\documentclass[]{article}

\usepackage{pgfplots}

\begin{document}



\begin{tikzpicture}
    \begin{axis}[xbar,
                xbar=30pt,
                bar width=5,
                xmajorgrids = true,
                yticklabel style={/pgf/number format/1000 sep=,font=\tiny},  
                ytick=data,
                bar width= .2cm,
                y=0.2cm,
                nodes near coords align = {horizontal},
                nodes near coords,
                nodes near coords align=right,
                point meta=rawx,
                every node near coord/.style={color=black,font=\tiny},
                x coord trafo/.code={\pgfmathparse{#1>500 ? 500+(#1-500)/2 : #1}},
                x coord inv trafo/.code={\pgfmathparse{#1>500 ? 500+(#1-500)*2 : #1}},
                xtick={0,500,1000,2000,3000}
              ]

        \addplot[draw=green,fill=green!50,enlargelimits=0.25]
            coordinates{
                  (3133,1)  (731,2)  (1196,3)  (210,4)  (83,5)  (312,6)  (40,7)  (36,8)  (76,9)  (15,10)  (8,11)  (38,12)  (9,13)  (7,14)  (20,15)  (3,16)  (2,17)  (13,18)
                  (2,19)  (4,20)  (3,21)  (2,22)  (2,23)  (2,24)  (1,26)  (1,27)  (1,28)  (1,30)  (2,31)  (2,33)  (1,35)  (1,36) 
            };
    \end{axis}
\end{tikzpicture}

\end{document}
Jake
  • 232,450
  • I agree with @Jake, the picture in the question is far more readable than the thing you want to achieve. – Nico Feb 10 '14 at 14:46
2

I don't know tikz and so I don't expect that this implementation is anywhere close to optimal. I merely provide this answer to suggest to you that when dealing with data that spans orders of magnitude, the use of logarithmic axes is a very common (and preferred) way to collapse the data into something comprehensible.

I know you said you didn't want a logarithmic scale, because non scientists don't understand it. But I think you should reconsider that notion (people grasp the notion of Richter Scale, which is logarithmic).

What I tried to do here was to make the x data the log10 of what it had been. In such a fashion, the revised plot spans from 0 to 3.5 (meaning 10^0 to 10^3.5), which is not so spread out as a linear representation with which you started.

I merely suggest an answer like this as food for thought. (And I don't know how or I would have labeled the horizontal axis with the following labels: 1, 3.13, 10, 31.3, 100, 313, 1000, 3130, so as to assist the non-scientist)

\documentclass[]{article}

\usepackage{pgfplots}
\usepackage{pgfplotstable}

\begin{document}

\title{Title}
\author{Author}
\date{Today}
\maketitle

\pgfplotsset{width=15cm}

\begin{tikzpicture}
    \begin{axis}[xbar stacked, nodes near coords,
                xbar=30pt,
                bar width=5,
                xmajorgrids = true,
                yticklabel style={/pgf/number format/1000 sep=,font=\tiny},  
                ytick=data,
                bar width= .2cm,
                    nodes near coords align = {horizontal},
                        nodes near coords,
                        nodes near coords align=right,
                        every node near coord/.style={color=black,font=\tiny}
              ]

        \addplot[draw=green,fill=green!50,enlargelimits=0.25]
            coordinates{
                  (log10(3133),1)  (log10(731),2)  (log10(1196),3)  (log10(273),4)  (log10(83),5)  (log10(312),6)  (log10(40),7)  (log10(36),8)  (log10(76),9)  (log10(15),10)  (log10(8),11)  (log10{38},12)  (log10(9),13)  (log10(7),14)  (log10(20),15)  (log10(3),16)  (log10(2),17)  (log10(13),18)
                  (log10(2),19)  (log10(4),20)  (log10(3),21)  (log10(2),22)  (log10(2),23)  (log10(2),24)  (log10(1),26)  (log10(1),27)  (log10(1),28)  (log10(1),30)  (log10(2),31)  (log10(2),33)  (log10(1),35)  (log10(1),36) 
            };
    \end{axis}
\end{tikzpicture}

\end{document}

enter image description here

  • 1
    You can simply set xmode=log in the OP's code to take the log of all the data, with the added benefit of keeping the tick label values untransformed (which helps "non-scientists" understand the plot more easily). It's worth pointing out that using logarithmic bar plots is considered bad practice by some, since the origin of the bars is arbitrary in a log plot. – Jake Feb 11 '14 at 06:25
  • @Jake Interesting point about log bar plots. My only rejoinder would be that, for plotting non-negative integer data, that complaint can be rebutted by the fact that your smallest data cannot fall below 1 = 10^0 (as in the current case). – Steven B. Segletes Feb 11 '14 at 10:54
  • @Jake is there an xmode to get log10 instead of log, since I would agree with the OP that log base e would be confusing to non-scientists? – Steven B. Segletes Feb 11 '14 at 13:15
  • You can set log basis x=10 (or some other value). The tick positions use basis 10 by default (ticks at 10^0, 10^1, etc.). I would probably just print the untransformed values at the end of the bars, (as long as the range isn't too large). – Jake Feb 11 '14 at 13:58