Tables are a common feature in academic writing, often used to summarize research results. Mastering the art of table construction in LaTeX is therefore necessary to produce quality papers and with sufficient practice one can print beautiful tables of any kind.
Keeping in mind that LaTeX is not a spreadsheet, it makes sense to use a dedicated tool to build tables and then to export these tables into the document. Basic tables are not too taxing, but anything more advanced can take a fair bit of construction; in these cases, more advanced packages can be very useful. However, first it is important to know the basics. Once you are comfortable with basic LaTeX tables, you might have a look at more advanced packages or the export options of your favorite spreadsheet. Thanks to the modular nature of LaTeX, the whole process can be automated in a fairly comfortable way.
LaTeX has built-in support to typeset tables and provides two environments: tabular and table . To typeset material in rows and columns, the tabular environment is needed; the optional table environment is a container for floating material similar to figure , into which a tabular environment may be included.
The table environment contains the caption and defines the float for the table, i.e., where in the document the table should be positioned and whether we want it to be displayed centered. The \caption and \label commands can be used in the same way as for pictures. For more information about the table environment, see the Floating with table section.
In any case, the actual content of the table is contained within the tabular environment.
The tabular environment can be used to typeset tables with optional horizontal and vertical lines. LaTeX determines the width of the columns automatically.
The first line of the environment has the form:
\begintabular>[pos]table spec>
The table spec argument tells LaTeX the alignment to be used in each column and the vertical lines to insert.
The number of columns does not need to be specified as it is inferred by looking at the number of arguments provided. It is also possible to add vertical lines between the columns here. The following symbols are available to describe the table columns (some of them require that the package array has been loaded):
l | left-justified column |
c | centered column |
r | right-justified column |
p | paragraph column with text vertically aligned at the top |
m | paragraph column with text vertically aligned in the middle (requires array package) |
b | paragraph column with text vertically aligned at the bottom (requires array package) |
| | vertical line |
|| | double vertical line |
By default, if the text in a column is too wide for the page, LaTeX won’t automatically wrap it. Using p you can define a special type of column which will wrap-around the text as in a normal paragraph. You can pass the width using any unit supported by LaTeX, such as 'pt' and 'cm', or command lengths, such as \textwidth . You can find a list in chapter Lengths.
The optional parameter pos can be used to specify the vertical position of the table relative to the baseline of the surrounding text. In most cases, you will not need this option. It becomes relevant only if your table is not in a paragraph of its own. You can use the following letters:
b | bottom |
c | center (default) |
t | top |
To specify a font format (such as bold, italic, etc.) for an entire column, you can add > < \format >before you declare the alignment. For example \begin < tabular > < > < \bfseries >l c > < \itshape >r > will indicate a three column table with the first one aligned to the left and in bold font, the second one aligned in the center and with normal font, and the third aligned to the right and in italic. The "array" package needs to be activated in the preamble for this to work.
In the first line you have pointed out how many columns you want, their alignment and the vertical lines to separate them. Once in the environment, you have to introduce the text you want, separating between cells and introducing new lines. The commands you have to use are the following:
& | column separator |
\\ | start new row (additional space may be specified after \\ using square brackets, such as \\[6pt] ) |
\hline | horizontal line |
\newline | start a new line within a cell (in a paragraph column) |
\cline | partial horizontal line beginning in column i and ending in column j |
Note, any white space inserted between these commands is purely down to one's preferences. I personally add spaces between to make it easier to read.
This example shows how to create a simple table in LaTeX. It is a three-by-three table, but without any lines.
\begintabular> l c r > 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \endtabular>
Expanding upon that by including some vertical lines:
\begintabular> l | c | r > 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \endtabular>
To add horizontal lines to the very top and bottom edges of the table:
\begintabular> l | c | r > \hline 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \\ \hline \endtabular>
And finally, to add lines between all rows, as well as centering (notice the use of the center environment - of course, the result of this is not obvious from the preview on this web page):
\begincenter> \begintabular> l | c | r > \hline 1 & 2 & 3 \\ \hline 4 & 5 & 6 \\ \hline 7 & 8 & 9 \\ \hline \endtabular> \endcenter>
\begincenter> \begintabular> | l | c | r > \hline 1 & 2 & 3 \\ \hline 4 & 5 & 6 \\ \hline 7 & 8 & 9 \\ \hline \endtabular> \endcenter>
1 2 3 4 5 6 7 8 9 <|l||c|||r>\hline 1&2&3\\\hline 4&5&6\\\hline \hline 7&8&9\\\hline \end>>
\begintabular>|r|l|> \hline 7C0 & hexadecimal \\ 3700 & octal \\ \cline2-2> 11111000000 & binary \\ \hline \hline 1984 & decimal \\ \hline \endtabular>
LaTeX's algorithms for formatting tables have a few shortcomings. One is that it will not automatically wrap text in cells, even if it overruns the width of the page. For columns that will contain text whose length exceeds the column's desired width, it is recommended that you use the p attribute and specify the desired width of the column (although it may take some trial-and-error to get the result you want). For a more convenient method, have a look at The tabularx package, or The tabulary package.
Instead of p , use the m attribute to have the lines aligned toward the middle of the box or the b attribute to align along the bottom of the box.
Here is a simple example. The following code creates two tables with the same code; the only difference is that the last column of the second one has a defined width of 5 centimeters, while in the first one we didn't specify any width. Compiling this code:
\documentclassarticle> \usepackage[english]babel> \begindocument> Without specifying width for last column: \begincenter> \begintabular>| l | l | l | l |> \hline Day & Min Temp & Max Temp & Summary \\ \hline Monday & 11C & 22C & A clear day with lots of sunshine. However, the strong breeze will bring down the temperatures. \\ \hline Tuesday & 9C & 19C & Cloudy with rain, across many northern regions. Clear spells across most of Scotland and Northern Ireland, but rain reaching the far northwest. \\ \hline Wednesday & 10C & 21C & Rain will still linger for the morning. Conditions will improve by early afternoon and continue throughout the evening. \\ \hline \endtabular> \endcenter> With width specified: \begincenter> \begintabular> | l | l | l | p5cm> |> \hline Day & Min Temp & Max Temp & Summary \\ \hline Monday & 11C & 22C & A clear day with lots of sunshine. However, the strong breeze will bring down the temperatures. \\ \hline Tuesday & 9C & 19C & Cloudy with rain, across many northern regions. Clear spells across most of Scotland and Northern Ireland, but rain reaching the far northwest. \\ \hline Wednesday & 10C & 21C & Rain will still linger for the morning. Conditions will improve by early afternoon and continue throughout the evening. \\ \hline \endtabular> \endcenter> \enddocument>
You get the following output:
Note that the first table has been cropped, since the output is wider than the page width.
Sometimes it is necessary to not rely on the breaking algorithm when using the p specifier, but rather specify the line breaks by hand. In this case it is easiest to use a \parbox :
\begintabular>cc> boring cell content & \parbox[t]5cm>rather long par\\new par> \endtabular>
Here the t argument controls the placement of the text inside the box. Other allowed values are c for center and b for bottom.
To tweak the space between columns (LaTeX will by default choose very tight columns), one can alter the column separation: \setlength < \tabcolsep > < 5pt >. The default value is 6pt.
One can also introduce a horizontal space with hspace like this: \begin < tabular >< r@ < \hspace < 1in >> rr > There are different options for the hspace length.
Re-define the \arraystretch command to set the space between rows:
\renewcommand\arraystretch>1.5>
Default value is 1.0.
An alternative way to adjust the rule spacing is to add \noalign < \smallskip >before or after the \hline and \cline < i-j >commands:
\begintabular> | l | l | r | > \hline\noalign\smallskip> \multicolumn2>c>Item> \\ \cline1-2>\noalign\smallskip> Animal & Description & Price (\$) \\ \noalign\smallskip>\hline\noalign\smallskip> Gnat & per gram & 13.65 \\ & each & 0.01 \\ Gnu & stuffed & 92.50 \\ Emu & stuffed & 33.33 \\ Armadillo & frozen & 8.99 \\ \noalign\smallskip>\hline \endtabular>
You may also specify the skip after a line explicitly using glue after the line terminator
\begintabular>ll> \hline Mineral & Color \\[1cm] Ruby & red \\ Sapphire & blue \\ \hline \endtabular>
If you use some LaTeX environments inside table cells, like verbatim or enumerate :
\begintabular>c c> \hline \beginverbatim> code \endverbatim> & description \\ \hline \endtabular>
you might encounter errors similar to
! LaTeX Error: Something's wrong--perhaps a missing \item.
To solve this problem, change column specifier to "paragraph" ( p , m or b ).
\begintabular>m5cm> c>
It is possible to define many identically aligned columns at once using the * < num > < str >syntax. This is particularly useful when your table has many columns.
Here is a table with six centered columns flanked by a single column on each side:
\begintabular>l*6>c>r> Team & P & W & D & L & F & A & Pts \\ \hline Manchester United & 6 & 4 & 0 & 2 & 10 & 5 & 12 \\ Celtic & 6 & 3 & 0 & 3 & 8 & 9 & 9 \\ Benfica & 6 & 2 & 1 & 3 & 7 & 8 & 7 \\ FC Copenhagen & 6 & 2 & 1 & 3 & 5 & 8 & 7 \\ \endtabular>Column specification using > and
The column specification can be altered using the array package. This is done in the argument of the tabular environment using > < \command >for commands executed right before each column element and < < \command >for commands to be executed right after each column element. As an example: to get a column in math mode enter: \begin < tabular > < >< $ >c> . Another example is changing the font: \begin < tabular > < > < \small >c > to print the column in a small font.
The argument of the > and < specifications must be correctly balanced when it comes to < and >characters. This means that > < \bfseries >is valid, while > < \textbf >will not work and > < \textbf <>is not valid. If there is the need to use the text of the table as an argument (for instance, using the \textbf to produce bold text), one should use the \bgroup and \egroup commands: > < \textbf\bgroup >c < < \egroup >produces the intended effect. This works only for some basic LaTeX commands. For other commands, such as \underline to underline text, it is necessary to temporarily store the column text in a box using lrbox . First, you must define such a box with \newsavebox < \boxname >and then you can define:
>\beginlrbox>\boxname> >% l% \endlrbox>% \underline\unhbox\boxname> >% >
This stores the text in a box and afterwards, takes the text out of the box with \unhbox (this destroys the box, if the box is needed again one should use \unhcopy instead) and passing it to \underline . (For LaTeX2e, you may want to use \usebox < \boxname >instead of \unhbox\boxname .)
This same trick done with \raisebox instead of \underline can force all lines in a table to have equal height, instead of the natural varying height that can occur when e.g. math terms or superscripts occur in the text.
Here is an example showing the use of both p < . >and > < \centering >:
\begintabular>>\centering>p3.5cm>>\centering>p3.5cm> > Geometry & Algebra \tabularnewline \hline Points & Addition \tabularnewline Spheres & Multiplication \endtabular>
Note the use of \tabularnewline instead of \\ to avoid a Misplaced \noalign error.
The column separator can be specified with the @ < . >or ! < . >constructs.
It typically takes some text as its argument, and when appended to a column, it will automatically insert that text into each cell in that column before the actual data for that cell. The @ < . >command kills the inter-column space and replaces it with whatever is between the curly braces. To keep the initial space, use ! < . >. To add space, use @ < \hspace < ''width'' >> .
Admittedly, this is not that clear, and so will require a few examples to clarify. Sometimes, it is desirable in scientific tables to have the numbers aligned on the decimal point. This can be achieved by doing the following:
\begintabular>r@.>l> 3 & 14159 \\ 16 & 2 \\ 123 & 456 \\ \endtabular>
The space-suppressing qualities of the @-expression actually make it quite useful for manipulating the horizontal spacing between columns. Given a basic table, and varying the column descriptions:
\begintabular> |l|l| > \hline stuff & stuff \\ \hline stuff & stuff \\ \hline \endtabular>
Instead of using @-expressions to build columns of decimals aligned to the decimal point (or equivalent symbol), it is possible to center a column on the decimal separator using the dcolumn package, which provides a new column specifier for floating point data. See the dcolumn package documentation for more information, but a simple way to use dcolumn is as follows.
\usepackagedcolumn> \ldots \newcolumntyped>[1]D.>\cdot>#1> > %the argument for d specifies the maximum number of decimal places \begintabular>l r c d1> > Left&Right&Center&\mathrmDecimal>\\ 1&2&3&4\\ 11&22&33&44\\ 1.1&2.2&3.3&4.4\\ \endtabular>
A negative argument provided for the number of decimal places in the new column type allows unlimited decimal places, but may result in rather wide columns. Rounding is not applied, so the data to be tabulated should be adjusted to the number of decimal places specified. Note that a decimal aligned column is typeset in math mode, hence the use of \mathrm for the column heading in the example above. Also, text in a decimal aligned column (for example the header) will be right-aligned before the decimal separator (assuming there's no decimal separator in the text). While this may be fine for very short text, or numeric column headings, it looks cumbersome in the example above. A solution to this is to use the \multicolumn command described below, specifying a single column and its alignment. For example to center the header Decimal over its column in the above example, the first line of the table itself would be Left & Right & Center & \multicolumn < 1 >< c > < Decimal >\\
To draw attention to particular entries in a table, it may be nice to use bold text. Ordinarily this is easy, but as dcolumn needs to see the decimal point it is rather harder to do. In addition, the usual bold characters are wider than their normal counterparts, meaning that although the decimals may align nicely, the figures (for more than 2--3 digits on one side of the decimal point) will be visibly misaligned. It is however possible to use normal width bold characters and define a new bold column type, as shown below. [ 1 ]
\usepackagedcolumn> %here we're setting up a version of the math fonts with normal x-width \DeclareMathVersionnxbold> \SetSymbolFontoperators>nxbold>OT1>cmr> b>n> \SetSymbolFontletters> nxbold>OML>cmm> b>it> \SetSymbolFontsymbols> nxbold>OMS>cmsy>b>n> \begindocument> \makeatletter \newcolumntyped>D.>.>-1> > %decimal column as before %wide bold decimal column \newcolumntypeB>[3]>\boldmath\DC@#1>#2>#3> >c\DC@end> > %normal width bold decimal column \newcolumntypeZ>[3]>\mathversionnxbold>\DC@#1>#2>#3> >c\DC@end> > \makeatother \begintabular>l l d> Type &M & \multicolumn1>c>N> \\ Normal & 1 & 22222.222 \\ Bold (standard)&10 & \multicolumn1>B.>.>-1> >22222.222>\\ Bold (nxbold)&100 & \multicolumn1>Z.>.>-1> >22222.222>\\ \endtabular> \enddocument>
It might be convenient to apply the same command over every cell of a row, just as for column. Unfortunately the tabular environment cannot do that by default. We will need tabu instead, which provides the \rowfont option.
\begintabu>XX> \rowfont\bfseries\itshape\large> Header1 & Header2 \\ \hline Cell2 & Cell2 \endtabu>
To complete this tutorial, we take a quick look at how to generate slightly more complex tables. Unsurprisingly, the commands necessary have to be embedded within the table data itself.
The command for this looks like this: \multicolumn < num _ cols >< alignment > < contents >. num_cols is the number of subsequent columns to merge; alignment is either l , c , r , or to have text wrapping specify a width p < 5.0cm >. And contents is simply the actual data you want to be contained within that cell. A simple example:
\begintabular> |l|l| > \hline \multicolumn2>|c|>Team sheet> \\ \hline GK & Paul Robinson \\ LB & Lucas Radebe \\ DC & Michael Duberry \\ DC & Dominic Matteo \\ RB & Dider Domi \\ MC & David Batty \\ MC & Eirik Bakke \\ MC & Jody Morris \\ FW & Jamie McMaster \\ ST & Alan Smith \\ ST & Mark Viduka \\ \hline \endtabular>
The first thing you need to do is add \usepackage < multirow >to the preamble [ 2 ] . This then provides the command needed for spanning rows: \multirow < ''num _ rows'' >< ''width'' > < ''contents'' >. The arguments are pretty simple to deduce ( * for the width means the content's natural width).
. \usepackagemultirow> . \begintabular> |l|l|l| > \hline \multicolumn3> |c| >Team sheet> \\ \hline Goalkeeper & GK & Paul Robinson \\ \hline \multirow4>*>Defenders> & LB & Lucas Radebe \\ & DC & Michael Duburry \\ & DC & Dominic Matteo \\ & RB & Didier Domi \\ \hline \multirow3>*>Midfielders> & MC & David Batty \\ & MC & Eirik Bakke \\ & MC & Jody Morris \\ \hline Forward & FW & Jamie McMaster \\ \hline \multirow2>*>Strikers> & ST & Alan Smith \\ & ST & Mark Viduka \\ \hline \endtabular>
The main thing to note when using \multirow is that a blank entry must be inserted for each appropriate cell in each subsequent row to be spanned.
If there is no data for a cell, just don't type anything, but you still need the "&" separating it from the next column's data. The astute reader will already have deduced that for a table of n columns, there must always be n − 1 ampersands in each row (unless \multicolumn is also used).
Here is a nontrivial example of how to use spanning in both directions simultaneously and have the borders of the cells drawn correctly:
\usepackagemultirow> \begintabular>cc|c|c|c|c|l> \cline3-6> & & \multicolumn4> c| >Primes> \\ \cline3-6> & & 2 & 3 & 5 & 7 \\ \cline1-6> \multicolumn1> |c >\multirow2>*>Powers> > & \multicolumn1> |c| >504> & 3 & 2 & 0 & 1 & \\ \cline2-6> \multicolumn1> |c ><> & \multicolumn1> |c| >540> & 2 & 3 & 1 & 0 & \\ \cline1-6> \multicolumn1> |c >\multirow2>*>Powers> > & \multicolumn1> |c| >gcd> & 2 & 2 & 0 & 0 & min \\ \cline2-6> \multicolumn1> |c ><> & \multicolumn1> |c| >lcm> & 3 & 3 & 1 & 1 & max \\ \cline1-6> \endtabular>
Here is another example exploiting the same ideas to make the familiar and popular "2x2" or double dichotomy:
\begintabular> r|c|c| > \multicolumn1>r><> & \multicolumn1>c>noninteractive> & \multicolumn1>c>interactive> \\ \cline2-3> massively multiple & Library & University \\ \cline2-3> one-to-one & Book & Tutor \\ \cline2-3> \endtabular>
The graphicx packages features the command \resizebox < width >< height > < object >which can be used with tabular to specify the height and width of a table. The following example shows how to resize a table to 8cm width while maintaining the original width/height ratio.
\usepackagegraphicx> % . \resizebox8cm>!> \begintabular>. \endtabular> >
Resizing table including the caption
\begintable>[h] \resizebox1.4\textwidth>!>\beginminipage>\textwidth> \begintabular>r|c|c|> & \multicolumn1>c>noninteractive> & \multicolumn1>c>interactive> \\ \cline2-3> massively multiple & Library & University \\ \cline2-3> one-to-one & Book & Tutor \\ \cline2-3> \endtabular> \caption[Table caption text]Table taken from \cite[p.10]refid> > \labeltable:name> \endminipage> > \endtable>
Alternatively you can use \scalebox < ratio > < object >in the same way but with ratios rather than fixed sizes:
\usepackagegraphicx> % . \scalebox0.7> \begintabular>. \endtabular> >
A table can be globally switched to a different font size by simply adding the desired size command (here: \footnotesize ) in the table scope, which may be after the \begin < table >statement if you use floats, otherwise you need to add a group delimiter.
\footnotesize \begintabular>| r | r || c | c | c |> % . \endtabular> >
\begintable>[h]\footnotesize \captionPerformance at peak F-measure> \begintabular>| r | r || c | c | c |> % . \endtabular> \endtable>
Alternatively, you can change the default font for all the tables in your document by placing the following code in the preamble:
\let\oldtabular\tabular \renewcommand\tabular>\footnotesize\oldtabular>
See Fonts for named font sizes. The table caption font size is not affected. To control the caption font size, see Caption Styles.
It is also possible to change the vertical space between rows using \renewcommand < \arraystretch > < 0.8 >before \begin < tabular >.
The xcolor package provides the necessary commands to produce tables with alternate row colors, when loaded with the table option. The command \rowcolors < > < > < > has to be specified right before the tabular environment starts.
\documentclassarticle> \usepackage[table]xcolor> \begindocument> \begincenter> \rowcolors1>green>pink> \begintabular>lll> odd & odd & odd \\ even & even & even\\ odd & odd & odd \\ even & even & even\\ \endtabular> \endcenter> \enddocument>
The command \hiderowcolors is available to deactivate highlighting from a specified row until the end of the table. Highlighting can be reactivated within the table via the \showrowcolors command. If while using these commands you experience "misplaced \noalign errors" then use the commands at the very beginning or end of a row in your tabular.
\hiderowcolors odd & odd & odd \\
odd & odd & odd \\ \showrowcolors