I have no doubt that datatool
is the way to go here. However, it is possible to use the code from my answer to the sorting question to do this.
You need to define a new comparator that compares only the first column. This particular implementation wants something that has a top level expansion into a row. E.g., you can define a macro for each row.
\def\rowi {C & foo & qwer \\}
\def\rowii {A & bar & asdf \\}
\def\rowiii{B & baz & zxcv \\}
The goal is to be able to write the following to get sorted rows.
\begin{tabular}{lll}
\toprule
Letters & Metasyntatic variables & Gibberish\\
\midrule
\sortfirstcol{\rowi\rowii\rowiii}
\bottomrule
\end{tabular}
In particular, the \sortfirstcol{\rowi\rowii\rowiii}
should expand to the sorted rows. As with \sortalpha
, \sortfirstcol
is just a simple macro that expands \sort
with the comparator \sort@firstcol
as its first argument.
\newcommand*\sortfirstcol{\sort\sort@firstcol}
The comparator isn't extremely complicated, but it does need to extract the first column of each argument. For that, we use a helper macro. And in keeping with the spirit of the original answer, this version is expandable.
\def\sort@firstcol#1#2{%
\expandafter\expandafter\expandafter
\sort@fc@helper\expandafter#1#2#1#2%
}
\def\sort@fc@helper#1\\#3\\#5#6#7{%
\ifnumcomp{\pdfstrcmp{#1}{#3}}<{0}
{#7{#5}{#6}}% else
{#7{#6}{#5}}%
}
The \expandafter
s are going to expand the first two arguments a single time. For example, if the comparator is "called" as \sort@firstcol{\rowi}{\rowii}{...}
, then it will expand to
\sort@fc@helper C & foo & qwer \\A & bar & asdf \\\rowi\rowii{...}
and so #1
will be the tokens "C ", #3
will be "A ", #5
will be \rowi
, #6
will be \rowii
, and lastly #7
will be the {...}
that is the continuation that gets passed to the comparator.
From here, it's identical to \sort@alpha
: it compares #1
and #3
, passing #5
and #6
to the continuation.
Lastly, due to the representation of the rows, the \sortend
and \sortoutput
macros should be set to just expand to their argument:
\newcommand*\sortoutput[1]{#1}
\newcommand*\sortend[1]{#1}
The following is a complete example using the above code and the code from the previous answer.
\documentclass{article}
\usepackage{etoolbox}
\usepackage{booktabs}
\makeatletter
% #1 - comparator
% #2 - token list to sort
\newcommand\sort[2]{%
\ifstrempty{#2}
{}% else
{%
\sort@begin#1{}#2\sort@s\sort@begin
}%
}
% helpers
\def\sort@s{\sort@s}
\def\ifsort@s#1{%
\ifx\sort@s#1%
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
% #1 - comparator
% #2 - tokens processed so far
% #3 - smallest token so far
% #4 - rest of the list
\def\sort@begin#1#2#3#4\sort@begin{%
\ifsort@s{#4}
{%
\sortend{#3}%
\sort#1{#2}%
}% else
{%
\sort@go#1{#2}{#3}#4\sort@go
}%
}
% #1 - comparator
% #2 - tokens processed so far
% #3 - smallest token so far
% #4 - token under consideration
% #5 - rest of the list
\def\sort@go#1#2#3#4#5\sort@go{%
#1{#3}{#4}{\sort@output#1{#2}{#5}}%
}
% #1 - comparator
% #2 - tokens processed so far
% #3 - rest of the list
% #4 - smaller of the two tokens
% #5 - larger of the two tokens
\def\sort@output#1#2#3#4#5{%
\ifsort@s{#3}
{%
\sortoutput{#4}%
\sort#1{#2{#5}}%
}% else
{%
\sort@begin#1{#2{#5}}{#4}#3\sort@begin
}%
}
\def\sort@numlt#1#2#3{%
\ifnumcomp{#1}<{#2}
{#3{#1}{#2}}% else
{#3{#2}{#1}}%
}
\def\sort@numgt#1#2#3{%
\ifnumcomp{#1}>{#2}
{#3{#1}{#2}}% else
{#3{#2}{#1}}%
}
\def\sort@alpha#1#2#3{%
\ifnumcomp{\pdfstrcmp{#1}{#2}}<{0}
{#3{#1}{#2}}% else
{#3{#2}{#1}}%
}
\def\sort@firstcol#1#2{%
\expandafter\expandafter\expandafter
\sort@fc@helper\expandafter#1#2#1#2%
}
\def\sort@fc@helper#1\\#3\\#5#6#7{%
\ifnumcomp{\pdfstrcmp{#1}{#3}}<{0}
{#7{#5}{#6}}% else
{#7{#6}{#5}}%
}
\newcommand*\sortnumlt{\sort\sort@numlt}
\newcommand*\sortnumgt{\sort\sort@numgt}
\newcommand*\sortalpha{\sort\sort@alpha}
\newcommand*\sortfirstcol{\sort\sort@firstcol}
\makeatother
% Change these to change out the sort outputs.
\newcommand*\sortoutput[1]{#1}
\newcommand*\sortend[1]{#1}
\begin{document}
\def\rowi {C & foo & qwer \\}
\def\rowii {A & bar & asdf \\}
\def\rowiii{B & baz & zxcv \\}
\begin{tabular}{lll}
\toprule
Letters & Metasyntatic variables & Gibberish\\
\midrule
\sortfirstcol{\rowi\rowii\rowiii}
\bottomrule
\end{tabular}
\end{document}
Finally, I should point out that this representation (that is, rows as macros) isn't necessary. Due to the way \sort
processes its arguments, one could easily write a comparator that allowed one to write the following.
\sortfirstcol{%
{C & foo & qwer}%
{A & bar & asdf}%
{B & baz & zxcv}%
}
\def\sortoutput#1{#1\\}
\def\sortend#1{#1\\}
Perhaps I should have done that. The comparator would be slightly simpler.
Also, as implemented, a space at the beginning or end of the first column matters. One could probably deal with that too.
Best Answer
It's been a while since I played with NumPy, but I used to call the
numpy.savetxt
function to export my data as a.csv
format:The sample file
mydata.csv
was generated accordingly:With the magic of
pgfplotstable
, we could do the following:I don't know if it's possible to remove the headers, but in any case I'll ask Christian Feuersänger about it.
:)
My good friend percusse provided a nice way of removing those headers:
Another, well, "way" of doing it is by tricking
numpy.savetxt
to act as:which will give us the following output file:
At last but not least,
datatool
can also be used. Unfortunately, it seems thatdatatool
does not recognize scientific notation as real values, so it treats like a string value. To fix it, I exported my.csv
file with a comma as delimiter and with fixed-point values:which will generate the following output:
Now, our LaTeX code, based on Alan's answer:
By using
\DTLdisplaydb
, headers are mandatory. If you don't want them, you can iterate through the values of the.csv
value instead.You can obtain more information on those packages by searching their tags: siunitx, datatool, pgfplotstable
Thanks to Jake, percusse and Alan.
:)