2

I would like to draw a XY-scatter plot using log scales on both axes. I would also like to depict error bars.

The standard method would be to draw horizontal and vertical error bars, but if I have a lot of data points, this looks messy. So I would like to draw the points as semi-transparent ellipses instead. The idea is that if the ellipse is fully above (or fully below) the diagonal line then we can be confident that 'our approach' wins or 'their approach' wins, and if it overlaps the diagonal line then we're not sure.

Partially inspired by this answer I've come up with something that almost works, except that the axes have linear scales. If I change them to log scales it breaks. So my question is: how can I make this work with log axes? (I'd be happy to express the width and height of the ellipses as relative errors or absolute errors, whatever is more convenient.)

\documentclass{standalone}

\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.5.1}

\begin{document}

\begin{tikzpicture}

\begin{axis} [
  %xmode=log, ymode=log, 
  %JW: Should be log scales but then the ellipses don't work :(
  ticklabel style={
        /pgf/number format/fixed,
        /pgf/number format/precision=2
  },
  height=85mm,
  width=85mm,
  xmin=1, xmax=1.3,
  ymin=1, ymax=1.3,
  xlabel = {Competitor's speedup factor},
  ylabel = {Our speedup factor},
]
\foreach \x/\y/\w/\h in {
  % x position / y position / width of ellipse / height of ellipse
  1.02/1.03/0.01/0.02, 
  1.04/1.05/0.02/0.01, 
  1.05/1.03/0.03/0.01,
  1.15/1.13/0.04/0.02,
  1.15/1.25/0.01/0.04
}{
  \edef\temp{\noexpand% JW: some unpleasant hackery needed here (https://tex.stackexchange.com/a/17817/25356)
  \draw[fill=black, draw=none, opacity=0.3] 
    (axis cs: \x,\y) circle [x radius=\w, y radius=\h];
  }
  \temp
} 
% JW: Plotting the y=x reference line
\draw[dotted] (rel axis cs: 0,0) -- (rel axis cs: 1,1);
\end{axis}
\end{tikzpicture}

\end{document}

Output of the code above

1 Answer 1

3

It is clear why it "does not work": in logarithmic coordinates you cannot add coordinates in the usual way, so the radii are interpreted differently than you want. However, it is easy to fix this using calc.

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{calc}
\pgfplotsset{compat=1.5.1}

\begin{document}

\begin{tikzpicture}

\begin{axis} [
  xmode=log, ymode=log, 
  %JW: Should be log scales but then the ellipses don't work :(
  ticklabel style={
        /pgf/number format/fixed,
        /pgf/number format/precision=2
  },
  height=85mm,
  width=85mm,
  xmin=1, xmax=1.3,
  ymin=1, ymax=1.3,
  xlabel = {Competitor's speedup factor},
  ylabel = {Our speedup factor},
]
\foreach \x/\y/\w/\h in {
  % x position / y position / width of ellipse / height of ellipse
  1.02/1.03/0.01/0.02, 
  1.04/1.05/0.02/0.01, 
  1.05/1.03/0.03/0.01,
  1.15/1.13/0.04/0.02,
  1.15/1.25/0.01/0.04
}{
  \edef\temp{% JW: some unpleasant hackery needed here (https://tex.stackexchange.com/a/17817/25356)
  \noexpand\path[fill,fill opacity=0.3] 
  let \noexpand\p1=($(axis cs: \x+\w,\y+\h)-(axis cs: \x-\w,\y-\h)$)
  in ($(axis cs: \x+\w,\y+\h)!0.5!(axis cs: \x-\w,\y-\h)$)
  circle[x radius=\noexpand\x1/2,y radius=\noexpand\y1/2];
  }
  \temp
} 
% JW: Plotting the y=x reference line
\draw[dotted] (rel axis cs: 0,0) -- (rel axis cs: 1,1);
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

Of course, under the transformation to logarithmic coordinates an ellipse will be mapped to a different shape. A first order approximation of the transformed ellipses is given by

\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.5.1}

\begin{document}

\begin{tikzpicture}

\begin{axis} [
  xmode=log, ymode=log, 
  %JW: Should be log scales but then the ellipses don't work :(
  ticklabel style={
        /pgf/number format/fixed,
        /pgf/number format/precision=2
  },
  height=85mm,
  width=85mm,
  xmin=1, xmax=1.3,
  ymin=1, ymax=1.3,
  xlabel = {Competitor's speedup factor},
  ylabel = {Our speedup factor},
]
\foreach \x/\y/\w/\h in {
  % x position / y position / width of ellipse / height of ellipse
  1.02/1.03/0.01/0.02, 
  1.04/1.05/0.02/0.01, 
  1.05/1.03/0.03/0.01,
  1.15/1.13/0.04/0.02,
  1.15/1.25/0.01/0.04
}{\pgfmathsetmacro{\mylooseness}{sqrt(min(\w/\h,\h/\w))}
  \edef\temp{% JW: some unpleasant hackery needed here (https://tex.stackexchange.com/a/17817/25356)
  \noexpand\path[fill,fill opacity=0.3,looseness=\mylooseness] (axis cs: \x-\w,\y) to[out=90,in=180]
  (axis cs: \x,\y+\h) to[out=0,in=90] (axis cs: \x+\w,\y)  to[out=-90,in=0]
  (axis cs: \x,\y-\h) to[out=180,in=-90] cycle;
  }
  \temp
} 
% JW: Plotting the y=x reference line
\draw[dotted] (rel axis cs: 0,0) -- (rel axis cs: 1,1);
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .