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.

I have several tables where I have tables which may look like this:

-------------------------------------
| X | Y | X + Y | X - Y | (X + Y)/2 |
-------------------------------------
|   |   |       |       |           |
|   |   |       |       |           |
|   |   |       |       |           |
-------------------------------------

I mean X, Y are the data and columns 3, 4, 5 are derived from X and Y.

Typing in contents of column 3, 4, 5 are subject to human error and mistakes (can be embarrassing). I was looking to get an idea as to how you solve this problem in LaTeX tables. Is there a package capable of doing this?

When you copy-paste an Excel table, there is very little scope for such errors. Is something similar possible in LaTeX?

share|improve this question
    
I suppose you want the calculations to be made automatically while printing the results upon compilation, right? –  azetina Oct 13 '12 at 3:28
1  
I'm sure datatool can also be used for this. –  Werner Oct 13 '12 at 4:32
    
The following question is only about sums, but maybe it's still it's a duplicate: How can I automatically calculate sums in a LaTeX table? –  Hendrik Vogt Oct 13 '12 at 10:36

3 Answers 3

One way to do this would be to use pgfplotstable as in the example that follows. If you need to do more complex analysis, you can create a csv file that can be editted in excel and imported using pgfplotstable or datatool package. You will find quite a few examples of it under datatool and pgfplotstable tag.

\documentclass{article}
\usepackage{pgfplotstable}
\begin{document}
  \pgfplotstableread[col sep = comma]{
    x,y,
    1,6,
    2,4,
    3,5,
    4,7,
    5,8,
  } \data

  \begin{table}
   \pgfplotstableset{create on use/a/.style={create col/expr={\thisrow{x}+\thisrow{y}}}}
   \pgfplotstableset{create on use/b/.style={create col/expr={\thisrow{x}-\thisrow{y}}}}
   \pgfplotstableset{create on use/c/.style={create col/expr={(\thisrow{x}+\thisrow{y})/2}}}
   \pgfplotstabletypeset[columns={x,y,a,b,c},
     columns/x/.style={column name={$x$}, column type={c}, },
     columns/y/.style={column name={$y$}, column type={c}, },
     columns/a/.style={column name={$x+y$}, column type={c}, },
     columns/b/.style={column name={$x-y$}, column type={c}, },
     columns/c/.style={column name={$(x+y)/2$}, column type={c}, },
   ]{\data}
 \end{table}
\end{document}

sample table

The following example adds some more eye-candy and illustrates how to import data from a file.

\documentclass{article}
\usepackage{pgfplotstable}  % Typeset table and manipulate column entries
\usepackage{booktabs}       % Nicer horizontal rules for tables
%\usepackage{array}         % To align column entries by decimal separator

\usepackage{filecontents}   % To illustrate importing data from external file
\begin{filecontents*}{data.csv} % Sample contents of data.csv file
    x,      y,
    1,      6,
    2,      4,
    3,      5,
    4,      7,
    5,      8,
    4.4,    7,
    512,    81,
\end{filecontents*}
\pgfplotstableread[col sep = comma]{data.csv}\data

\begin{document}

\begin{table}[h]
    \pgfplotstableset{create on use/a/.style={create col/expr={ \thisrow{x}+\thisrow{y}}}}
    \pgfplotstableset{create on use/b/.style={create col/expr={ \thisrow{x}-\thisrow{y}}}}
    \pgfplotstableset{create on use/c/.style={create col/expr={(\thisrow{x}+\thisrow{y})/2}}}
    \pgfplotstabletypeset%
    [columns={x,y,a,b,c},
        every head row/.style={before row=\toprule, after row=\midrule},
        every nth row={5}{before row=\midrule},
        every last row/.style={after row=\bottomrule},
        columns/x/.style={column name={$x$}, dec sep align},
        columns/y/.style={column name={$y$}, dec sep align},
        columns/a/.style={column name={$x+y$}, dec sep align},
        columns/b/.style={column name={$x-y$}, dec sep align},
        columns/c/.style={column name={$\frac{x+y}{2}$}, dec sep align},
    ]{\data}
\end{table}
\end{document}

another sample table

share|improve this answer
    
It would be nice if you could change the alignment in the last column. I am sure siunitx or dcolumn could help here but if it can be done with pgfplotstabble (only) then that'd be nicer. –  Marc van Dongen Oct 13 '12 at 5:20
1  
@MarcvanDongen this can be done by adding dec sep align to corresponding column style. I have added an example to the answer. –  mythealias Oct 13 '12 at 7:26

An example using the spreadtab package:

\documentclass{article}
\usepackage{spreadtab}
\usepackage{array}
\usepackage{booktabs}
\usepackage{amsmath}

\begin{document}

\noindent\begin{spreadtab}{{tabular}{*{5}{>{$}r<{$}}}}
\toprule
@x & @y & @x+y & @x-y & @\dfrac{x+y}{2}\\
\midrule
1 & 2 & \STcopy{>1,v4}{!a2+b2} & \STcopy{>1,v4}{!a2-b2} & \STcopy{>1,v4}{!(a2+b2)/2} \\
3 & 2 & & &  \\
-3 & -6 & & &   \\
9 & -2 & & &  \\
10 & 5 & & &  \\
\bottomrule
\end{spreadtab}

\end{document}

enter image description here

share|improve this answer
    
very nice, but would look even nicer if the headers for the last three columns were more centered over the column contents. –  barbara beeton Oct 13 '12 at 12:25

This can also be accomplished using the collcell package which allows one to intercept each of the data elements from tabular/array for further processing.

enter image description here

Notes:

  • I used array below as the material was all math. This could just as easily have been tabular.

  • I have used newtoggle from the etoolbox package as I prefer that syntax versus the \newif syntax. But if you don't want to include an additional package it should be pretty straightforward to adapt this to use \newif or some other conditional methods.

  • The pgf package package was used for math processing but any method of computing the values you need would work. Note that pgf uses degrees for the trignometric functions by default. Apply the rad() function if that is not desired: sin(rad(<value>)).

Code:

\documentclass{article}

\usepackage{amsmath} 
\usepackage{etoolbox}% for toggles
\usepackage{collcell} 
\usepackage{xifthen} 
\usepackage{pgf}% for math

\newcommand{\ColumnXData}{}
\newcommand{\ColumnYData}{}
\newcommand*{\ComputeColumnA}[1]{}%

\newtoggle{DoneWithHeader}
\togglefalse{DoneWithHeader}
\newcommand{\DoneWithHeader}{\global\toggletrue{DoneWithHeader}}

% Automatically reset this toggle at the end of the array
\let\OldEndArray\endarray
\def\endArray{\global\togglefalse{DoneWithHeader}\OldEndArray}

% Define the operations for the various columns.

\newcommand*{\FormatNumber}[2][]{\pgfmathprintnumber[precision=5,#1]{#2}}
\newcommand*{\ComputeColumnU}{%
    \pgfmathparse{\ColumnXData + \ColumnYData}%
    \FormatNumber{\pgfmathresult}%
}%
\newcommand*{\ComputeColumnV}{
    \pgfmathparse{(\ColumnXData)^2 + 3*(\ColumnYData)}%
    \FormatNumber{\pgfmathresult}%
}%
\newcommand*{\ComputeColumnW}{%
    \pgfmathparse{sin(\ColumnXData + \ColumnYData)}%
    \FormatNumber{\pgfmathresult}%
}%

\newcounter{ColumnCount}
\newcommand*{\SetColumnData}[1]{%
    \iftoggle{DoneWithHeader}{%
        \stepcounter{ColumnCount}
        % This could clearly be made more efficient but is easier to read this way
        \ifthenelse{\arabic{ColumnCount}=1}{\xdef\ColumnXData{#1}#1}{}
        \ifthenelse{\arabic{ColumnCount}=2}{\xdef\ColumnYData{#1}#1}{}
        \ifthenelse{\arabic{ColumnCount}=3}{\ComputeColumnU}{}
        \ifthenelse{\arabic{ColumnCount}=4}{\ComputeColumnV}{}
        \ifthenelse{\arabic{ColumnCount}=5}{\ComputeColumnW\setcounter{ColumnCount}{0}}{}
        % Note that in the above we wsed the fact that column `W` is last  
        % to reset the column counter so that for the next row we know 
        % which are the data columns.  If this won't always be the case
        % you could manually \setcounter{ColumnCount}{0} at the end of each row.
    }{%
        #1%
    }%
}%
\newcolumntype{C}{>{\collectcell\SetColumnData}{c}<{\endcollectcell}}
\newcolumntype{L}{>{\collectcell\SetColumnData}{l}<{\endcollectcell}}
\newcolumntype{R}{>{\collectcell\SetColumnData}{r}<{\endcollectcell}}


\begin{document}
$
\begin{array}{C C C C L}
 x & y & x + y & x^2+3y & \sin (x+y) \DoneWithHeader \\ 
 10 & 20 & & & \\
 20 & 40 & & & \\
\end{array}
$
\end{document}
share|improve this answer
    
+1, I like the way you used collcell in combination with a “toggle”. But why do you use \ComputeColumn?{#1}? The \Compute* macros don't have an argument and in those columns #1 are empty anyway. In fact, you can remove {#1} entirely from those columns. For efficiency and clarity I'd use \ifcase: \ifcase\value{ColumnCount}\xdef\ColumnXData{#1}#1\or\xdef\ColumnYData{#1}#1\or\‌​ComputeColumnU\or\ComputeColumnV\or\ComputeColumnW\setcounter{ColumnCount}{-1}\fi‌​\stepcounter{ColumnCount} –  Qrrbrbirlbel Nov 27 '12 at 1:25
    
Thanks. Have updated solution to eliminate the unused #1. –  Peter Grill Nov 27 '12 at 1:36

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.