4

I am making an xbar plot with pgfplots. I want this plot to show the results from a test, where people in different age classes are given scores. For each of these age classes a single person is the winner. See the attached latex file containing the dataset "data.dat", with four columns: Age-interval, Y-position, Score, and Name.

I want my xbar plot to have different y tick labels on, respectively, the left and the right side y axes. The left side y tick labels denotes the age intervals of the persons tested (20-30, 30-40,...), while the right side y tick labels should denote the winner in each of the age intervals (Peter, Jeff, ...).

Two questions:

(1) I am not able to make a left side and a right side set of y tick labels simultaneously. How can I do that?

Adding two extra lines of code, for showing right side y tick labels (code block starting with "% (2) "), does not solve my problem, only shifting it from showing only the left side y tick labels to showing only the right side y tick labels

(2) How do I prevent the plot title to overlap with the x tick labels?

here is my code:

{\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}
\pgfplotsset{compat=1.3}

% test scores and person names
\begin{filecontents}{data.dat}
Age-interval        Y-Position         Score        Name
20-30               1                  15           Peter
30-40               2                  20           Jeff
40-50               3                  12           Steve
50-60               4                  24           John 
\end{filecontents}

\begin{document}
\begin{tikzpicture}

\begin{axis}[
    title = {Test score},
    xbar,     
    bar width=2pt,
    ytick=data,
    width=8 cm,
    height=5 cm,
    xmin=-1,
    xmax = 100,
    xticklabel pos = upper,
    tick align = outside,
    %
    % (1) add left side y tick labels
    yticklabel pos=left, 
    yticklabels from table={data.dat}{Age-interval},
    %
    % (2) add righ side y tick labels
    %    yticklabel pos=right, 
    %    yticklabels from table={data.dat}{Name},
    %
    ylabel={Age intervals (yr)},
]
\addplot table [
    y=Y-Position,
    x=Score, 
] {data.dat};
\end{axis}

\end{tikzpicture}
\end{document}
Martin Scharrer
  • 262,582

2 Answers2

5

Instead of using the title key, I would use xlabel, since that's what you're trying to get and it gets the position right (the fact that the title overlaps the labels is a bug though, I'll file a report).

For printing the names on the right-hand side of the axis, you could use extra y ticks, with every extra y tick/.style={yticklabel pos=right, yticklabels from table={data.dat}{Name}}.

A different approach would be to use nodes near coords to place the names near the bars. For this, you have to set point meta=explicit symbolic in the axis to tell pgfplots not to use the x value for the labels (explicit) and to switch off the number parser for the meta data (symbolic), and meta=Names in the \addplot table options. To position the labels to the right of the bars, you can use every node near coord/.append style={anchor=west}.


Labels on right side of plot

\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.dat}
Age-interval        Y-Position         Score        Name
20-30               1                  15           Peter
30-40               2                  20           Jeff
40-50               3                  12           Steve
50-60               4                  24           John 
\end{filecontents}

\begin{document}
\begin{tikzpicture}

\makeatletter
\begin{axis}[
    xlabel={Test score},
    xbar,     
    bar width=2pt,
    ytick=data,
    width=8 cm,
    height=5 cm,
    xmin=-1,
    xmax = 100,
    xticklabel pos = upper,
    tick align = outside,
    yticklabel pos=left, 
    yticklabels from table={data.dat}{Age-interval},
    ylabel={Age intervals (yr)},
    extra y ticks={1,...,4},
    every extra y tick/.style={
        yticklabel pos=right,
        yticklabels from table={data.dat}{Name}}
]
\addplot table [
    y=Y-Position,
    x=Score
] {data.dat};
\end{axis}

\end{tikzpicture}
\end{document}

Labels near bars

\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.dat}
Age-interval        Y-Position         Score        Name
20-30               1                  15           Peter
30-40               2                  20           Jeff
40-50               3                  12           Steve
50-60               4                  24           John 
\end{filecontents}

\begin{document}
\begin{tikzpicture}

\makeatletter
\begin{axis}[
    xlabel={Test score},
    xbar,     
    bar width=2pt,
    ytick=data,
    width=8 cm,
    height=5 cm,
    xmin=-1,
    xmax = 100,
    xticklabel pos = upper,
    tick align = outside,
    yticklabel pos=left, 
    yticklabels from table={data.dat}{Age-interval},
    ylabel={Age intervals (yr)},
    nodes near coords,
    every node near coord/.append style={anchor=west},
    point meta=explicit symbolic
]
\addplot table [
    y=Y-Position,
    x=Score,
    meta=Name
] {data.dat};
\end{axis}

\end{tikzpicture}
\end{document}
Jake
  • 232,450
  • Thans a lot Jake! I have a follow-up question regarding your code in "Labels on right side of plot". You are defining "extra y ticks={1,...,4}," because the original y ticks consisted of {1,2,3,4}. But if the original data shfts, having y ticks = {1,2,3,4,5}, then I will have to change your code to "extra y ticks={1,...,4,5},". How could "extra y ticks" be adjusted automatically to fit the values in "y ticks"? – Espen Donali Feb 01 '12 at 12:02
3

Your first problem can be solved by using a second axis with the option yticklabel pos = right to get the other y-labels on the right side.

Your second problem - the overlapping of title and x tick labels - can be addressed by shifting the title upwards using the option title style = {yshift=<length>}.

\documentclass{article}
\usepackage{pgfplots}
\usepackage{filecontents}
\pgfplotsset{compat=1.3}

% test scores and person names
\begin{filecontents}{data.dat}
Age-interval        Y-Position         Score        Name
20-30               1                  15           Peter
30-40               2                  20           Jeff
40-50               3                  12           Steve
50-60               4                  24           John 
\end{filecontents}

\begin{document}
\begin{tikzpicture}

\begin{axis}[
    title = {Test score},
    title style = {yshift = 10pt},
    xbar,     
    bar width=2pt,
    ytick=data,
    width=8 cm,
    height=5 cm,
    xmin=-1,
    xmax = 100,
    xticklabel pos = upper,
    tick align = outside,
    yticklabel pos=left, 
    yticklabels from table={data.dat}{Age-interval},
    ylabel={Age intervals (yr)},
]
\addplot table [
    y=Y-Position,
    x=Score, 
] {data.dat};
\end{axis}
\begin{axis}[
    xbar,     
    bar width=2pt,
    ytick=data,
    width=8 cm,
    height=5 cm,
    xmin=-1,
    xmax = 100,
    xticklabels = none,
    tick align = outside,
    yticklabel pos=right, 
    yticklabels from table={data.dat}{Name},
    ylabel={Winner},
]
\addplot table [
    y=Y-Position,
    x=Score, 
] {data.dat};
\end{axis}


\end{tikzpicture}
\end{document}
Philipp
  • 3,815
  • Thanks a lot! That solved a lot of problems:) My own solution, which did not work, is close to yours with an extra axis environment, but I did not include an extra \addplot line. Why do I have to have an \addplot line in each of the two axis environments? It seems like waste of code to plot the same data twice? – Espen Donali Jan 31 '12 at 15:16
  • @EspenDonali: I was a bit in a hurry and couldn't figure out how to get the y tick labels for the y axis on the right positioned automatically without repeating the plot. But you're right, plotting data twice is a waste of resources. If you have a solution that avoids this I'd be grateful if you could post it. – Philipp Jan 31 '12 at 20:34