表の配置・整形

表のキャプションが本文と表にぴったり張り付いて見えるのは、気のせいではありません。LaTeX の標準クラスは \abovecaptionskip を 10pt、\belowcaptionskip0pt に設定しており(articlereportbook すべて同じ)、キャプションは 図のために 調整されています。表のキャプションは上に置くのが慣例なので、空きのある側が上、ゼロの側が表に接する——これが「なんとなく窮屈」の正体です。このページは tabular外側 、つまり table 環境による配置とキャプション、紙幅からはみ出す表の畳み方、横向きへの回転、そして表に注をつける threeparttable を扱います。中身の組み方そのものは「tabular の基本」と「列指定・整列・幅」の担当です。

なぜ表は「浮く」のか——table 環境と tabular の違い

表を途中で改ページできないからです。tabular が作るのは 一つの大きな箱 で、箱はページ境界で分割できません。ソースのその位置に置こうとして残りが足りなければ、大きな空白ができるか、表が押し出されて版面が崩れます。そこで LaTeX は表と図を 浮動体(フロート) として扱い、本文の流れから切り離して収まりのよい場所へ送ります。これを使う仕掛けが table 環境 で、中に tabular を入れ、\caption{…} で「表 1」のような番号付きの見出しを与え、\label{…}\ref{…} で本文から参照できるようにします。本文には「表~\ref{tab:sales} に示すとおり」と 番号で参照 を書けばよく、表が何ページ先へ送られても番号は自動で正しくなります(~ は語と番号が行末で離れないようにする連結空白です)。

document.tex
\usepackage{booktabs}
\usepackage{float}   % needed only for the [H] specifier

\begin{table}[htbp]
  \centering
  \caption{Quarterly sales}
  \label{tab:sales}          % \label always AFTER \caption
  \begin{tabular}{@{}lrr@{}}
    \toprule
    Quarter & Sales & YoY \\
    \midrule
    Q1 & 1{,}200 & +5\% \\
    Q2 & 1{,}350 & +8\% \\
    \bottomrule
  \end{tabular}
\end{table}

% in the body: as Table~\ref{tab:sales} shows ...

配置指定 [htbp] と [H] の違い

[htbp]許可する場所の集合[H]フロートをやめる指示 です。\begin{table} の直後の角括弧には、h(その位置)・t(ページ上端)・b(ページ下端)・p(フロート専用ページ)を並べます。何も書かなければ article でも book でも既定は tbp ——つまり h は最初から候補に入っていません。重要なのは、並べた順序が処理の順序を変えない ことです。LaTeX は常に t→b→p の順に試すので、[htbp][bpht] はまったく同じ働きをします。角括弧は希望の表明ではなく、許可の列挙 だと考えてください。

先頭の感嘆符 ![!ht] など)は「このフロートに限り 内部の制限を無視して 配置を試みよ」という指示で、「ここに置け」という意味ではありません。その「内部の制限」は実際の数値で決まっており、article の既定では \topfraction = 0.7(ページ上部をフロートが占めてよい割合)、\bottomfraction = 0.3、\textfraction = 0.2(本文が最低限占めるべき割合)、\floatpagefraction = 0.5(フロート専用ページを作る下限)、そして 1 ページに置けるフロートは上部 2 個・下部 1 個・合計 3 個(\topnumber\bottomnumber\totalnumber)です。表がなかなか出てこないのは、たいていこのどれかに引っかかっているからで、! はこの判定をゆるめるだけです。本当にその場に固定したいなら、float パッケージの [H] ——\usepackage{float} のうえで \begin{table}[H] と書くと、表はフロートをやめてソースのその位置に組まれます(結果としてページ下部に大きな空白が残ることがあります)。H は「フロートしないフロート」だと理解しておくと事故が減ります。

指定意味既定の関連パラメータ
hソースのその位置に(here)。h 単独は許されず、自動的に t が補われる既定の tbp には含まれない
t本文ページの上端\topfraction = 0.7、\topnumber = 2
b本文ページの下端\bottomfraction = 0.3、\bottomnumber = 1
p本文を含まないフロート専用ページ\floatpagefraction = 0.5
!このフロートに限り上記の割合と個数の制限を無視する。位置指定ではない\textfraction = 0.2、\totalnumber = 3 も対象
Hフロートをやめてその場に固定する。float パッケージが必要標準 LaTeX にはない指定

キャプションは表の上・図の下——そして \label は \caption の後

この二つが、キャプションまわりの事故の大半を占めます。\caption{…} はフロートに番号付きの見出しを与え、article なら「Table 1:」、book なら「Table 1.1:」のように 通し番号 を自動で振ります。表と図はカウンタが別なので番号が混ざることはありません。\caption[短い見出し]{本文の見出し} と任意引数を付けると、図表一覧 には短い方が、本文には長い方が載ります。そして 番号を進めるのは \caption なので、\label は必ず \caption の後に置いてください。逆にすると \ref は一つ前の番号を指し、しかもエラーは出ません。配置の慣習は、表はキャプションを上に、図は下に ——表は見出しを読んでから中身に入り、図は見てから説明を読む、という順序の違いです。LaTeX 上は \captiontabular に書けば上、 に書けば下になります。

ここで冒頭の実測値が効いてきます。標準クラスの \abovecaptionskip は 10pt、\belowcaptionskip0pt。つまり空きは キャプションの外側にだけ あり、キャプションと本体のあいだには何も入りません。図(キャプションが下)ではこれで問題ありませんが、表(キャプションが上)では キャプションが表に接します。直し方は二つ。素の LaTeX なら \setlength{\belowcaptionskip}{6pt} を宣言する、caption パッケージを使うなら \usepackage[skip=6pt]{caption} あるいは \captionsetup[table]{skip=6pt} と表だけに指定する方法です。フォント・区切り・幅などキャプションの書式そのものを整えるのも caption パッケージの仕事で、詳細は「キャプションとサブ図」のページにあります。

中身を中央に置くのは \centering です。フロートの中では center 環境(\begin{center}…\end{center})ではなく \centering を使うのが定石——center 環境は前後に余分な縦の空きを入れますが、\centering は宣言だけなので余計な空白が出ません。中央ではなく右端に寄せたいときは、中身の前に \hfill を置けば横方向の余りがすべて左に集まります。ちなみに フロートの中の \centering は安全 ですが、p{幅} 列の中に \centering を書くのは話が別で、その列が表の最後の列だと行終端の \\ が壊れ、! Extra alignment tab has been changed to \cr. が出ます。列指定の中に書く \centering の扱いは「列指定・整列・幅」の担当です。

LaTeX の表の幅が本文からはみ出すとき

縮小する前に、幅の内訳を測ってくださいlcr の列は折り返さないので、列が多ければ表は \textwidth を超えます。ところが超過分の正体はたいてい文字ではなく 列間の余白 です。実例として、12 列・見出し 1 行・データ 1 行の booktabs の表を測ると幅 412.95pt、article(10pt・a4 相当の既定)の \textwidth は 345pt なので 68pt 溢れます。同じ表を \tabcolsep = 0pt で組み直すと 268.95pt ——差は ちょうど 144pt2 × 12 列 × 6pt です。つまり 表の幅の 35% は文字ではなく余白 でした。

この内訳が分かると、対処の優先順位が変わります。よく勧められる「フォントを一段小さくする」は、同じ表で \small にしても 392.77pt\footnotesize にしても 372.55pt で、どちらも 345pt に届きません。\tabcolsep長さであってフォント依存ではない ため、文字を小さくしても 144pt の余白はそのまま残るからです。一方 \setlength{\tabcolsep}{3pt} と半分にするだけで 340.95pt ——本文サイズのまま収まりました。\small\tabcolsep = 4pt の併用なら 344.77pt です。まず余白、次に書体、最後に拡大縮小、という順序で考えてください。

latex
\usepackage{graphicx}   % for \resizebox

% 1. trim the padding first -- \tabcolsep is 6pt on EACH side of EVERY column
\begingroup
\setlength{\tabcolsep}{3pt}
\begin{tabular}{@{}lrrrrrrrrrrr@{}}  % @{} also removes the outer 2 x 6pt
  ...
\end{tabular}
\endgroup

% 2. only then consider a smaller size, or scaling as a last resort
\resizebox{\textwidth}{!}{%
  \begin{tabular}{lrrrrr}
    ...
  \end{tabular}%
}

列指定の両端に置く @{} も、外側の \tabcolsep を落として表を本文の左端にそろえます(実測で 2 × 6pt = 12pt ちょうど)。booktabs の表でよく見る書き方です。それでも収まらない場合の最後の手段が graphicx\resizebox{幅}{高さ}{中身} で、片方を ! にすると縦横比を保って拡縮します。ただしこれは 中身を「拡大縮小」する ので、先ほどの表を \resizebox{\textwidth}{!} に通すと倍率は 345 ÷ 412.95 = 0.836、本文 10pt の文字は 8.4pt 相当に、\toprule の 0.8pt は 0.67pt になります。文字も罫線も本文と釣り合わなくなるので、応急処置 と割り切ってください。\resizebox の代わりに adjustbox を使うと \begin{adjustbox}{width=\textwidth}…\end{adjustbox} と環境としても書けます。行の高さを少し空けたいときは \renewcommand{\arraystretch}{1.2}(既定は 1)で、10pt 文書の 3 行の表なら 0.2 × 3 × 12pt = 7.2pt だけ背が高くなります。

ここまでで収まらないなら、道具を替えるべき合図です。列を目標幅まで自動で伸縮させる tabularxX 列や、tabularraytblr は「高機能な表環境」のページが扱います。行数が多くてページに収まらない 場合は幅ではなく長さの問題で、改ページできる longtable の出番——こちらは「ページをまたぐ表」のページです。この二つは、本ページの拡大縮小や回転より先に検討する価値があります。

表を横向きにする——sidewaystable と rotatebox

縦向きのページにどうしても収まらない大きな表は、rotating パッケージの sidewaystable 環境table の代わりに使えば、90 度回転して 1 ページを使い切れます。キャプションと番号も一緒に回り、図表一覧にもきちんと載ります。両面組版では、見開きで読みやすいよう回転の向きが自動で調整されます。図には対応する sidewaysfigure があります。表の 一部だけを任意の角度で回したい なら、同じく graphicxrotating\rotatebox{角度}{中身} ——見出しセルだけを \rotatebox{90}{long column name} で立てる使い方が典型です(角度は反時計回りが正)。

document.tex
\usepackage{rotating}
\usepackage{booktabs}

\begin{sidewaystable}
  \centering
  \caption{A wide table turned 90 degrees}
  \label{tab:wide}
  \begin{tabular}{@{}lrrrrrrrr@{}}
    \toprule
    Region & Q1 & Q2 & Q3 & Q4 & Total & Prev & Diff & Ratio \\
    \midrule
    East & 120 & 135 & 128 & 142 & 525 & 500 & +25 & 105\% \\
    \bottomrule
  \end{tabular}
\end{sidewaystable}

注意すべき境界が一つあります。rotating が扱うのは 箱(ボックス)の回転 であり、箱は必ず 1 ページに収まります。したがって 複数ページにわたる横向きの本文 は作れません。それが必要なときは lscape(本文だけを横向きに組む)か、PDF のページ自体を回転させる pdflscape を使います。pdflscape なら PDF ビューアで読むときにページが自動で回るので、画面で読まれる文書には特に向いています。横向きかつ複数ページの表なら pdflscapelongtable の組み合わせになります。

表に注をつける——threeparttable

tabular の中で \footnote を使うと、注はページ下部へ飛ぶか、そもそも出力されません。これを解決するのが Donald Arseneau の threeparttable です。名前のとおり表を 「タイトル(キャプション)/本体(tabular)/注(tablenotes)」の三部構成 として扱い、注を表と同じ幅にそろえて表の直下に 置きます。パッケージ自身の説明にあるとおり threeparttable は単体ではフロートしない ので、番号と配置が欲しければ全体を table(あるいは二段組の全幅なら table*)で包みます。

document.tex
\usepackage{booktabs}
\usepackage{threeparttable}

\begin{table}[htbp]
  \centering
  \begin{threeparttable}
    \caption{Yield by variety}
    \label{tab:yield}
    \begin{tabular}{@{}lrr@{}}
      \toprule
      Variety & Yield\tnote{a} & Price\tnote{b} \\
      \midrule
      Koshihikari & 540 & 380 \\
      Akitakomachi & 520 & 360 \\
      \bottomrule
    \end{tabular}
    \begin{tablenotes}
      \footnotesize
      \item[a] Kilograms per 10 a.
      \item[b] Wholesale price per kilogram.
    \end{tablenotes}
  \end{threeparttable}
\end{table}

threeparttable 環境のなかに \captiontabulartablenotes の順で並べるだけです。注の対応づけは 手動 ——セルに \tnote{a} と標識を置き、tablenotes のなかに同じ記号で \item[a] … と書きます。自動番号にしなかった理由は作者自身が .sty の冒頭に書き残しています。曰く「現時点で注に自動的なところは何もない……\footnote による自動採番はきわめて使いにくいだろう、とりわけ 多くの表が一つの注を繰り返し参照する から。もし便利で優雅な自動の仕組みがあるなら聞かせてほしい」。1990 年代に書かれたパッケージが、いまも同じ設計のまま使われています。

オプション効果
para複数の注を改行せず、続けて一段落に組む
flushleft注のぶら下げインデントをなくす
online\item の標識を上付きにせず、本文と同じ大きさで組む
normal既定の書式に戻す(文書全体の設定を個々の表で打ち消す)

これらは \usepackage[para]{threeparttable} のように文書全体へ、または \begin{tablenotes}[flushleft] のように表ごとに指定できます。threeparttable はキャプションの書式そのものは整えないので、見出しらしい体裁にしたいときは caption パッケージと併用します。ページをまたぐ長い表(longtable)に注をつけたい場合は、姉妹パッケージの threeparttablex を使ってください。

  • 表が思った位置に出ない — まず [htbp] の並び順ではなく 許可の集合 を見直す。それでも動かないなら \topfraction などの制限に当たっているので [!ht]、本当に固定したいなら float[H]
  • キャプションが表に貼り付く\belowcaptionskip が既定 0pt。\setlength{\belowcaptionskip}{6pt}caption パッケージの skip=
  • 表が紙幅からはみ出す — 先に \tabcolsep@{}、次に \small、最後に \resizebox。列を折り返してよいなら p{幅}tabularx
  • 行数が多すぎる — 幅ではなく長さの問題なので longtable。横向きかつ複数ページなら pdflscape と併用。
  • セルに脚注をつけたい\footnote ではなく threeparttable\tnotetablenotes