Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

pgfplotstable offers the iflessthan key to define a custom comparison function:

/pgfplots/iflessthan/.code args={##1##2##3##4}{<...>}

I just don't know how to use it, there's no example in the manual. What I'd like to do is to sort a table by a column that contains integers, but they are too big for sort cmp={int <} to handle. Here is a small examples that generates the table I want, but without the desired sorting:

\documentclass[a4paper,10pt]{scrartcl}

\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}

\usepackage{pgfplotstable}
\usepackage{etoolbox}

\begin{document}
  \pagestyle{empty}
  \pgfplotstableread[trim cells=true,col sep=semicolon,header=false]{
% column 3: index, column 6: value
;;;20730691;;;500
;;;20730690;;;450
;;;44569;;;400
;;;;;;345
;;;6366132;;;300
;;;6366133;;;300
;;;6366134;;;NER
}{\privateTable}
  \pgfplotstablesort[sort,sort key={[index]3},sort cmp={string <},sort ]{\publicTable}{\privateTable}
  \pgfplotstabletypeset[columns={3,6},
                        columns/3/.style={column name=index,string type},
                        columns/6/.style={column name=value,
                          assign cell content/.code={% convert NER to ner
                            \ifstrequal{##1}{NER}{%
                              \pgfkeyssetvalue{/pgfplots/table/@cell content}{ner}
                            }{%
                              \pgfkeyssetvalue{/pgfplots/table/@cell content}{\pgfmathprintnumber{##1}}
                            }%
                          }
                        },
                        row predicate/.code={% skip rows with empty index
                          \pgfplotstablegetelem{#1}{3}\of{\publicTable}
                          \ifnum\pdfstrcmp{\pgfplotsretval}{}=0
                            \pgfplotstableuserowfalse
                          \fi
                        },
                        ]\publicTable
\end{document}

When I change sort cmp from int < to string <, I get three missing number, treated as zero errors. This is why I'd like to define a comparison function based on \ifnumless (from the etoolbox package).

How can I do that?


When I just copy the string < style definition from pgfplotsutil.code.tex, I get numerous

!Parameters must be numbered consecutively.  
<to be read again>;  
                   ##

errors:

\pgfplotstablesort[sort,
  sort key={index},
  iflessthan/.code args={##1##2##3##4}{%
    \t@pgfplots@toka=\expandafter{##1}%
    \t@pgfplots@tokb=\expandafter{##2}%
    \edef\pgfplots@loc@TMPa{{\the\t@pgfplots@toka}{\the\t@pgfplots@tokb}}%
    \expandafter\pgfplotsutilstrcmp\pgfplots@loc@TMPa
    \if1\pgfplotsretval ##3\else ##4\fi
  }
  ]{\publicTable}{\privateTable}
share|improve this question
add comment

1 Answer 1

up vote 5 down vote accepted

The problem is present because of the empty sort keys. Note that sorting is applied long before your row predicates are considered.

Consequently, the iflessthan code needs to be made aware of empty keys (the defaults are not).

That is why you observe "! Missing number, treated as zero." whenever you try to use int < instead of string <: TeX tries to compare an empty string with something else. And it "informs" you that it replaced the empty string by a zero. If you hit enter to see the output after all those errors, you will see a correctly sorted table.

A possible fix - as desired, with \ifnumless -, could be

\pgfplotsset{
    my own </.style={%
        /pgfplots/iflessthan/.code args={##1##2##3##4}{%
            \edef\X{##1} \ifx\X\empty \def\X{-2000000} \fi%
            \edef\Y{##2} \ifx\Y\empty \def\Y{-2000000} \fi%
            \ifnumless{\X}{\Y}{##3}{##4}%
        },%
    },
}

You only need to use my own < instead of string < to activate it.

It works as follows: it defines a code key with four arguments. Then, it defines \X to be the Expanded DEFinition of the first argument, checks if it is the empty string, and assigns some "huge" negative value if that is the case. After doing the same for the second argument, it compares the two numbers and executes ##3 if the comparison is true and ##4 if not.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.