# pgfplots: by row, ranking particular column

I have a dataset in which rows indicate years and columns firms. For each year, I want to plot the 1st firm's rank against the others.

In the example below, 2013 is tied for 5th (if this is too tricky, I can break the rounding) as cells 1 to 8 (ex. cell 0) in the 2013 row are ordered: 0.67 (F3; 1st) > 0.54 (F6; 2nd) > 0.48 (F2; 3rd) > 0.46 (F8; 4th) > 0.38 (F1 & F4; joint 5th). In years 2014 onwards, F1 is ranked 6th.

\documentclass{article}
\usepackage{pgfplotstable}
\usepackage{tikz}
\usepackage{pgfplots}

\begin{document}

% year    F1      F2      F3      F4      F5      F6      F7      F8
2013  0.38    0.48    0.67    0.38    0.34    0.54    0.32    0.46 \\
2014  0.37    0.48    0.70    0.39    0.34    0.54    0.31    0.50 \\
2015  0.35    0.44    0.68    0.38    0.30    0.53    0.28    0.49 \\
2016  0.33    0.43    0.67    0.35    0.29    0.51    0.29    0.47 \\
}\datatable

\begin{tikzpicture}
\begin{axis}[
ylabel = rank, y dir = reverse,
]

\addplot table [x expr=\coordindex, y expr= % what goes here?
] {\datatable};

\end{axis}
\end{tikzpicture}

\end{document}


A hand-coded version of the result I want is below.

• For me it is still unclear how the resulting plot should look like. Could you add a sketch of the result. Then I think we will be able to provide a solution without multiple iterations because the question is "unclear". Mar 7 '19 at 6:13
• Thanks Stefan. I've added a plot and tried to clarify the text. Mar 7 '19 at 8:32

So you are searching for something like the following? Hopefully this is self-explanatory ...

% used PGFPlots v1.16
\documentclass[border=5pt]{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{
compat=1.3,
/pgf/declare function={
MyRank(\a,\b,\c,\d,\e,\f,\g,\h) =
ifthenelse( \a == min(\a,\b,\c,\d,\e,\f,\g,\h), 1,
ifthenelse( \b == min(\a,\b,\c,\d,\e,\f,\g,\h), 2,
ifthenelse( \c == min(\a,\b,\c,\d,\e,\f,\g,\h), 3,
ifthenelse( \d == min(\a,\b,\c,\d,\e,\f,\g,\h), 4,
ifthenelse( \e == min(\a,\b,\c,\d,\e,\f,\g,\h), 5,
ifthenelse( \f == min(\a,\b,\c,\d,\e,\f,\g,\h), 6,
ifthenelse( \g == min(\a,\b,\c,\d,\e,\f,\g,\h), 7,
8)))))));
},
}
% (please note that I have changed the first value of F5)
year    F1      F2      F3      F4      F5      F6      F7      F8
2013  0.38    0.48    0.67    0.38    0.30    0.54    0.32    0.46
2014  0.37    0.48    0.70    0.39    0.34    0.54    0.31    0.50
2015  0.35    0.44    0.68    0.38    0.30    0.53    0.28    0.49
2016  0.33    0.43    0.67    0.35    0.29    0.51    0.29    0.47
}\datatable
\begin{document}
\begin{tikzpicture}
\begin{axis}[
ylabel=rank,
y dir=reverse,
xtick distance=1,
ytick distance=1,
]
x expr=\coordindex,
y expr={
MyRank(
\thisrow{F1},
\thisrow{F2},
\thisrow{F3},
\thisrow{F4},
\thisrow{F5},
\thisrow{F6},
\thisrow{F7},
\thisrow{F8}
)
}
] {\datatable};
\end{axis}
\end{tikzpicture}
\end{document}


• Thank you Stefan. Is there an easy way of extending this beyond nine columns? (My non-minimal problem has over 20.) Mar 8 '19 at 13:07
• Unfortunately I don't have an idea ... Mar 8 '19 at 15:02
• Hi Stefan - I've just taken a closer look at the above: it seems to return arg min, rather than returning the rank of the F1 column. I've tried to extend the ifthenelse structure, but get nests on both sides on the conditional statements, so am not sure that this is an efficient way forward. I wonder if a recursive approach makes more sense. Mar 12 '19 at 16:13
• That is true. But pgfplots does not have a rank function included, the same holds for gnuplot (as far as I know). I think that it would be much easier to determine the rank in an external program (like Excel), save the result in another table and plot this one ... Mar 12 '19 at 16:30
• Thanks Stefan. I've wondered how pointless it is to try to do this in PGF. I'm sticking at it so far as I've got one underlying dataset from which I want to generate a number of plots. From a maintenance point of view, I liked the idea of just running a bunch of PGF scripts on that one dataset. Mar 15 '19 at 12:30