This is a direct follow-up of https://tex.stackexchange.com/questions/62409. Jake showed how to create a contingency table with the pgfplotstable
package (and booktabs
). Integer size limitations hit pretty fast and I was wondering if there was a workaround or another recommended approach to deal with this.
The MWE example below has 3 example datasets: the first example has small integers and works, the second example has 'medium-size' integers and fails at the computation of the totals, and the third example has 'large' integers and fails everywhere. I insert a screenshot for each.
I made a lame attempt at wrapping the calls with \pgfkeys{/pgf/fpu}
, but did not succeed. My workaround was to use units that made the integers small, e.g. displaying thousands.
\documentclass[border=5pt]{standalone}
\usepackage{booktabs}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotstableset{col sep=comma}% needed here too...
%% Jake @ https://tex.stackexchange.com/questions/62409
\newcommand{\createcontingencytable}[4]{ %
% #1=table name
% #2=first column name
% #3=new row sum name
% #4=new column sum name
\pgfplotstablecreatecol[
create col/assign/.code={% In each row ...
\def\rowsum{0}
\pgfmathtruncatemacro\maxcolindex{\pgfplotstablecols-1}
% ... loop over all columns, summing up the elements
\pgfplotsforeachungrouped \col in {1,...,\maxcolindex}{
\pgfmathsetmacro\rowsum{\rowsum+\thisrowno{\col}}
}
\pgfkeyslet{/pgfplots/table/create col/next content}\rowsum
}
]{#3}{#1}%
%
% Transpose the table, so we can repeat the summation step for the columns
\pgfplotstabletranspose[colnames from={#2},input colnames to={#2}]{\intermediatetable}{#1}
%
% Sums for each column
\pgfplotstablecreatecol[
create col/assign/.code={%
\def\colsum{0}
\pgfmathtruncatemacro\maxcolindex{\pgfplotstablecols-1}
\pgfplotsforeachungrouped \col in {1,...,\maxcolindex}{
\pgfmathsetmacro\colsum{\colsum+\thisrowno{\col}}
}
\pgfkeyslet{/pgfplots/table/create col/next content}\colsum
}
]{#4}\intermediatetable
%
% Transpose back to the original form
\pgfplotstabletranspose[colnames from=#2, input colnames to=#2]{\contingencytable}{\intermediatetable}
}
%
%% Load data
\usepackage{filecontents}% for self-contained example
%% Example 1: OK
\begin{filecontents*}{data1.csv}
Duration,France,Germany
A,10,90
B,20,80
C,30,70
D,40,60
E,50,50
\end{filecontents*}
%% Example 2: Data OK, but Total too large
\begin{filecontents*}{data2.csv}
Duration,France,Germany
A,1000,9000
B,2000,8000
C,3000,7000
D,4000,6000
E,5000,5000
\end{filecontents*}
%% Example 3: Data too large
\begin{filecontents*}{data3.csv}
Duration,France,Germany
A,209207,31522
B,309251,68742
C,257560,90127
D,257613,125882
E,723154,813889
\end{filecontents*}
% Play around with data1.csv, data2.csv, and data3.csv
\pgfplotstableread{data1.csv}{\mydata}
%% Create the contingency table
\createcontingencytable{\mydata}{Duration}{Total}{Total}
\begin{document}
\pgfplotstabletypeset[
col sep = comma,
columns = {Duration, France, Germany, Total},
columns/Duration/.style = {string type},
]\contingencytable
\end{document}
Bonus Track [EDITED]: m̶y̶ ̶w̶o̶r̶k̶a̶r̶o̶u̶n̶d̶ the finished product, thanks to to great answers!
\documentclass[border=5pt]{standalone}
\usepackage{booktabs}
\usepackage[svgnames,table]{xcolor}% \rowcolors
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\pgfplotstableset{% pgfplotstable options
col sep = comma,
every head row/.style = {before row = \toprule, after row=\midrule},
every last row/.style = {after row=\bottomrule},
}
\pgfkeys{% \pgfkeys provides \pgfmathprintnumber[display]{} without pgfplots
/pgf/number format/.cd,
fixed,
fixed zerofill,
precision=0,
set thousands separator={,},
}
%% Jake @ https://tex.stackexchange.com/questions/62409
\newcommand{\createcontingencytable}[4]{ %
% #1=table name
% #2=first column name
% #3=new row sum name
% #4=new column sum name
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}% handle large integers
\pgfplotstablecreatecol[
create col/assign/.code={% In each row ...
\def\rowsum{0}
\pgfmathtruncatemacro\maxcolindex{\pgfplotstablecols-1}
% ... loop over all columns, summing up the elements
\pgfplotsforeachungrouped \col in {1,...,\maxcolindex}{
\pgfmathsetmacro\rowsum{\rowsum+\thisrowno{\col}}
}
\pgfkeyslet{/pgfplots/table/create col/next content}\rowsum
}
]{#3}{#1}%
%
% Transpose the table, so we can repeat the summation step for the columns
\pgfplotstabletranspose[colnames from={#2},input colnames to={#2}]{\intermediatetable}{#1}
%
% Sums for each column
\pgfplotstablecreatecol[
create col/assign/.code={%
\def\colsum{0}
\pgfmathtruncatemacro\maxcolindex{\pgfplotstablecols-1}
\pgfplotsforeachungrouped \col in {1,...,\maxcolindex}{
\pgfmathsetmacro\colsum{\colsum+\thisrowno{\col}}
}
\pgfkeyslet{/pgfplots/table/create col/next content}\colsum
}
]{#4}\intermediatetable
%
% Transpose back to the original form
\pgfplotstabletranspose[colnames from=#2, input colnames to=#2]{\contingencytable}{\intermediatetable}
\pgfkeys{/pgf/fpu=false}% Stop using fpu library
}
%
%% Load data and create the contingency table
\begin{filecontents*}{data4.csv}
Duration,France,Germany
A,209,32
B,309,69
C,258,90
D,258,126
E,723,814
\end{filecontents*}
\begin{filecontents*}{data5.csv}
Duration,France,Germany
A,209207,31522
B,309251,68742
C,257560,90127
D,257613,125882
E,723154,813889
\end{filecontents*}
\pgfplotstableread{data5.csv}{\mydata}
\createcontingencytable{\mydata}{Duration}{Total}{Total}
\begin{document}
\rowcolors{1}{}{gray!10}%
\renewcommand{\tabcolsep}{20pt}%
\renewcommand{\arraystretch}{1.5}%
\pgfplotstabletypeset[
every head row/.style = {%
before row={\toprule & \multicolumn{3}{c}{Unemployment (Thousands)}\\ \cmidrule{2-4}}},
columns = {Duration, France, Germany, Total},
columns/Duration/.style = {string type},
columns/Duration/.append style = {string replace={A}{$<$~1 month}},
columns/Duration/.append style = {string replace={B}{$>$~1 month and $<$~3 months}},
columns/Duration/.append style = {string replace={C}{$>$~3 month and $<$~6 months}},
columns/Duration/.append style = {string replace={D}{$>$~6 month and $<$~1 year}},
columns/Duration/.append style = {string replace={E}{$1$~year and over}},
columns/Duration/.append style = {column type = {l}},
]\contingencytable
\end{document}