# Sorting according to more than one key in pgfplotstable

Is it possible to sort rows of a pgfplotstable according to multiple keys?

For example, input file is as follows:

Mtx Kind P   Sp
A   LP   16  4.2
C   OPT  16  72.5
A   LP   64  20.3
B   OPT  16  5.7
B   OPT  64  16.4
A   LP   256 90.4


We want to sort by column Kind first, then by Mtx, then by P. Desired table should look like as follows:

Mtx Kind P   Sp
B   OPT  16  5.7
B   OPT  64  16.4
C   OPT  16  72.5
A   LP   16  4.2
A   LP   64  20.3
A   LP   256 90.4


I am able to sort more than one numeric column. However, since, I was not able to convert a string to a numeric value (e.g. via using hash of string), I could not sort such data. It is also ok to sort the file directly using multiple keys without using pgfplotstable.

-
Maybe use a electronic spreadsheet software (e.g. MS Excel, Ooo Calc) to do such thing –  Leo Liu Mar 16 '13 at 10:49
Dear @LeoLiu, thanks for advice, however input data file constantly changes so an automated system is required to generate latex document from input data file. Portability is great issue. Anyone can compile my latex code on any machine (windows, linux, etc) however running any scripts (shell, phyton, script for spreadsheet software, etc.) before latex does not preserve this portability. –  Kadir Mar 16 '13 at 12:49

Pgfplots comes with builtin support for single sort keys.

However, if is possible to plug in multiple sort keys -- with a bit of efford and inside knowledge:

\documentclass[a4paper]{standalone}

\usepackage{pgfplots}

\usepackage{pgfplotstable}

\begin{document}

\def\pgfplotsinvokeiflessthan#1#2#3#4{%
\pgfkeysvalueof{/pgfplots/iflessthan/.@cmd}{#1}{#2}{#3}{#4}\pgfeov
}%
\def\pgfplotsmulticmpthree#1#2#3#4#5#6\do#7#8{%
\pgfplotsset{string <}%
\pgfplotsinvokeiflessthan{#1}{#4}{%
% first key <:
#7%
}{%
\pgfplotsinvokeiflessthan{#4}{#1}{%
% first key >:
#8%
}{%
% first key ==:
\pgfplotsset{string <}%
\pgfplotsinvokeiflessthan{#2}{#5}{%
% second key <
#7%
}{%
\pgfplotsinvokeiflessthan{#5}{#2}{%
% second key >
#8%
}{%
% second key ==
\pgfplotsset{float <}%
\pgfplotsinvokeiflessthan{#3}{#6}{%
% third key <
#7%
}{%
% third key >=
#8%
}%
}%
}%
}%
}%
}%

\pgfplotstabletypeset[
create on use/sortkey/.style={
create col/assign/.code={%
\edef\entry{{\thisrow{Kind}}{\thisrow{Mtx}}{\thisrow{P}}}%
\pgfkeyslet{/pgfplots/table/create col/next content}\entry
}
},
sort key=sortkey,
sort cmp={%
iflessthan/.code args={#1#2#3#4}{%
\edef\temp{#1#2}%
\expandafter\pgfplotsmulticmpthree\temp\do{#3}{#4}%
},
},
sort,
columns/Mtx/.style={string type},
columns/Kind/.style={string type},
]{
Mtx Kind P   Sp
A   LP   16  4.2
C   OPT  16  72.5
A   LP   64  20.3
B   OPT  16  5.7
B   OPT  64  16.4
A   LP   256 90.4
}
\end{document}


The approach consists of two parts: (1) the creation of a temporary column called sortkey which expands to {A}{LP}{16} for the first row and (2) the definition of a customized sort cmp. The customized sort cmp here uses a multi-key comparison (lexicographical compare) with string < for the first two keys and float < for the third.

Note that sort key=sortkey instantiates the create on use specification while sort cmp defines the customized comparison.

The key sort activates the sort functionality

The approach is fairly general and should probably become a general-purpose utility; I will think about a suitable predefined style.

-