フロートと配置

\begin{figure} と書いた場所に図は出ません。LaTeX は図を本文の流れから切り離し、いったん 待ち行列 に預けて持ち歩き、ページの都合がついたところではじめて落とします。これがフロート(float、浮動体)で、[htbp] の四文字は「どこに落としてよいか」を伝える許可証にすぎません。この仕組みを知らずに [h] と書き続けると、図はかえって遠くへ飛びます。このページでは、フロートが動く理由、[htbp] の各文字が実際に意味するもの、[H][h!] の決定的な違い、\FloatBarrier\clearpage によるせき止め、配置パラメータ、そして ! LaTeX Error: Too many unprocessed floats. が出る本当の条件を扱います。

図が書いた場所に出ない理由

図や表が改ページで真っ二つになったら読めません。半分をここに、残りを次ページに——というわけにはいかないのです。そこで LaTeX は図表を 分割できない一つの箱 として扱い、本文の組版が進んだところでページの上端・下端・あるいは図表だけを集めた専用ページのいずれかを選んで落とします。これがフロートで、標準の環境は figuretable の二つです。手で位置を決めるのではなく、行分割と同じように 配置も最適化問題として解く ——それが TeX の一貫した設計思想です。

この設計には裏表があります。表の側は、図表が絶対に割れず、番号(「図 1」「表 2」)と \caption\label\ref による相互参照が勝手にそろうこと。裏の側は、書いた位置と出る位置がずれる こと。ただし後者は欠陥ではなく前提です。本文に「図 1 を参照」と番号で書ける以上、図が隣にある必要はない——だから 位置ではなく番号で参照する のが原則になります。LaTeX がフロートを処理するのは ソースに現れた順 なので、後ろの図が先の図を追い越して先に出ることもあります。「上の図」「下の図」と地の文に書くのが危険なのはこのためです。

[htbp] の h・t・b・p が実際に意味するもの

figuretable配置指定子 を省略可能引数として受け取ります。\begin{figure}[htbp] の角括弧がそれで、「この位置なら置いてよい」という許可の集合を伝えます。何も書かないと articlebook の既定値 tbp が使われ——ここに h は入っていません。つまり指定子を省いた図は、はじめから「その場」を候補にしていないのです。

指定子意味実際の挙動
hhere単独では使えない。LaTeX が t を補い、LaTeX Warning: 'h' float specifier changed to 'ht'. を出す
ttop本文ページの上端。既定では 2 個まで、高さは本文領域の 70% まで
bbottom本文ページの下端。既定では 1 個まで、高さは本文領域の 30% まで
ppage本文を含まないフロート専用ページ。ページの 50% 以上が埋まるときだけ作られる
!overrideこのフロートに限り、個数と高さの内部制限を無視する。位置候補は増えない
Hfloat パッケージ専用そもそもフロートにしない。float パッケージが無いと ! LaTeX Error: Unknown float option 'H'.

[h] の扱いは、多くの解説が「無視される」で済ませていますが、実際には LaTeX が 警告を出して黙って書き換えます\begin{figure}[h] を組むと LaTeX Warning: 'h' float specifier changed to 'ht'. がログに残り、指定は ht として扱われます。[h!] も同様で LaTeX Warning: '!h' float specifier changed to '!ht'. になります。この警告を読めば、なぜ図が上に飛んだのかがその場で分かります。もうひとつの誤解は文字の順序です。[bt] と書いても [tb] と書いても試行順は変わりません。 指定子は順番ではなく「許可した位置の集合」で、LaTeX 内部の試行順は固定です。結論として実務では、選択肢を狭めないこと——[tbp][htbp] と広く許すほど図は近くに落ち、[h] 一文字に絞るほど遠くへ飛びます。

latex
\begin{figure}[htbp]
  \centering
  \includegraphics[width=0.6\textwidth]{plot}
  \caption{Measured values against the model}
  \label{fig:result}
\end{figure}

% refer by number, not by position; ~ keeps word and number on one line
See Figure~\ref{fig:result} for the result.

[H][h!] の違い — 片方はフロートですらない

[H] は「[h!] よりさらに強い here」ではありません。そもそもフロート機構を通りません。 float パッケージは LaTeX 内部の \@xfloat を置き換え、指定子の先頭に H を見つけた瞬間に別のコードへ分岐します。つまり H は配置指定子として評価されず、図表は単なる大きなボックスとしてその場に組まれるのです。だから float を読み込まずに [H] と書くと ! LaTeX Error: Unknown float option 'H'. で止まります。対して [h!] は最後までフロートのままで、内部制限を無視するだけ。置けなければ普通に流れていきます。

違いは実際に組んでみると一目です。同じ本文の同じ位置に、ページ本文の半分の高さの図を [H][!h] で置き比べると、[H] の図はその場から動かず、入りきらない分だけ 本文ごと次のページへ送られます[!h] の図は警告を出したうえで、続く本文を追い越して次のページの上へ飛んでいきます。つまり [H] は「絶対にここ、代わりにページを割る」、[!h] は「なるべくここ、無理なら動く」。手順図やアルゴリズムの流れ図のように文の順序と結びついた小さな図には [H] が向きますが、大きな図に使うと前のページの下半分がまるごと空きます。\floatplacement{figure}{H} で文書全体の既定にすることもできますが、その代償はほぼ必ず大量の空白です。

latex
\usepackage{float}
% ...
\begin{figure}[H]   % not a float any more: pinned, page breaks around it
  \centering
  \includegraphics[width=0.6\textwidth]{diagram}
  \caption{Processing pipeline}
\end{figure}

フロートをせき止める — \FloatBarrier\clearpage

一番腹立たしいのは、ある節の図がその節に収まりきらず 次の節へ流れ込む ことです。第 2 節の図 3 が第 3 節の本文の途中に現れると、読者は自分がどこにいるのか分からなくなります。これを止めるのが placeins パッケージの \FloatBarrier で、Donald Arseneau が書き、パブリックドメインで公開されています。節ごとに区切りたければ各 \section の前に置くか、\usepackage[section]{placeins} を読み込めば \section の先頭に自動で挿入されます。

ここで訂正しておきたい通説があります。「\FloatBarrier は改ページしない」——これは 誤り です。placeins のソースを読むと、\FloatBarrier は保留中のフロートが残っているあいだ \newpage を発行して自分自身を呼び直し、それでも掃けなければ \clearpage に切り替えます。実際に、下に置いた [b] の大きな図を抱えた状態で \FloatBarrier を通すと、図は次のページに出て本文はその次のページから再開します——ページが二つ進みます。改ページしないのは、保留フロートが一つも無いときだけです。したがって両者の違いは「改ページの有無」ではなく、「無条件に改ページするか(\clearpage)、必要なときだけ改ページするか(\FloatBarrier)」 です。

latex
\usepackage{placeins}          % or [section] to barrier every \section
\usepackage{afterpage}
% ...
\section{Experiment}
% ... figures and tables ...
\FloatBarrier                  % nothing may cross this line
\section{Discussion}

% flush pending floats at the END of the current page, not right here
\afterpage{\clearpage}

\clearpage を書きたいがその場で改ページされては困る、という場面には afterpage パッケージの \afterpage{\clearpage} が効きます。いま組んでいるページが自然に終わったところで \clearpage を実行してくれるので、本文の途中に穴が空きません。もうひとつ、局所的な道具として \suppressfloats[t] があります。これは「このページの上端にはもうフロートを置くな」と指示するもので、placeins[section] オプションも見出しの直後に内部でこれを使っています。ちなみに [section] は既定でかなり厳格で、フロートが節の開始位置より上へ回り込むことすら禁じます。緩めたいときは [above][below] オプションを付けます。

フロート配置パラメータ — 図が「入らない」と言われる本当の理由

「上に置けるはずなのに置かれない」の答えは、たいてい 配置パラメータ にあります。LaTeX はページのどれだけをフロートに明け渡してよいかを比率と個数で持っていて、article クラスの既定値は \topfraction = 0.7、\bottomfraction = 0.3、\textfraction = 0.2、\floatpagefraction = 0.5、そして topnumber = 2、bottomnumber = 1、totalnumber = 3 です。つまり本文の高さの 70% を超える図は どうやっても上端には行けません[t] としか書いていなければ、その図は行き場を失って延々と後ろへ送られます。

パラメータarticle の既定値意味
\topfraction0.7ページ上端をフロートが占めてよい最大の割合
\bottomfraction0.3ページ下端をフロートが占めてよい最大の割合
\textfraction0.2本文ページに必ず残さねばならない本文の最小割合
\floatpagefraction0.5フロート専用ページを作るのに必要な最小の埋まり具合
topnumber2ページ上端に置けるフロートの最大個数
bottomnumber1ページ下端に置けるフロートの最大個数
totalnumber31 ページ全体に置けるフロートの最大個数
\dbltopfraction0.7二段組の figure* がページ上端を占めてよい最大の割合

比率は \renewcommand{\topfraction}{0.85}、整数は \setcounter{totalnumber}{5} で変更します。\topfraction を上げて \textfraction を下げると、上端により多くの図表が載り「入らないから次ページへ」の追い出しが減ります。実は [htbp]! は、この調整の 一回限りの局所版 です。二段組にも別の値があり、figure*\dbltopfraction に従います。ここで大事な事実がひとつ。二段組の figure*tp にしか置けません。 LaTeX の内部には二段抜きフロート用の「下端リスト」がそもそも存在せず、既定の指定子も tp です。\begin{figure*}[hb] と書いても警告すら出ずに、静かにページ上端へ回されます。

Too many unprocessed floats — 上限は 18 ではなく 52

待ち行列が溢れると ! LaTeX Error: Too many unprocessed floats. が出ます。ここで広く出回っている「フロートは 18 個まで」という数字は、もう古い ものです。latex.ltx は確かに \bx@A から \bx@R までの 18 個の箱を確保しますが、e-TeX が使える環境(いまのエンジンはすべてそうです)では続けて \bx@S\bx@Z\bx@AA\bx@ZZ を追加し、合計 52 個 になります。この拡張は LaTeX の 2015/10/01 リリースで入りました。実際に一つも配置できないフロートを並べて試すと、エラーが出るのはきっかり 53 個目 です。

エラーが出ても、あわてて図を減らす必要はありません。同じ 2015 年に入った \extrafloats{n} をプリアンブルに書けば箱を追加できます。実測では、52 個で溢れる文書に \extrafloats{40} を足すだけでエラーは消えます。ただし箱が足りないのは 症状であって原因ではない ことが多いのも事実です。溢れる文書はたいてい、置けないフロートを溜め込んでいます。[t] しか許していないのに本文高さの 70% を超える図がある、フロートのあいだに本文がほとんど無くて改ページの機会が生まれない、といった状況です。まずは指定子を [htbp] に広げ、ところどころに \clearpage を入れて掃き出すほうが、根治には近道です。関連して LaTeX Warning: Float too large for page by ...pt は「この図はページに載りきらないので専用ページに追い出した」という意味で、図を小さくするか用紙を変えるかの判断材料になります。

latex
% loosen the layout rules for the whole document
\renewcommand{\topfraction}{0.85}
\renewcommand{\textfraction}{0.1}
\renewcommand{\floatpagefraction}{0.75}
\setcounter{totalnumber}{5}

% allocate 40 more float boxes on top of the built-in 52
\extrafloats{40}

二つの図を横に並べる

フロートは中身を選ばないので、横並びは 一つの figure の中に箱を二つ作る だけで実現します。素の LaTeX なら minipage——指定した幅の「小さなページ」を作る環境です。二つを並べて間に \hfill(伸縮する水平の空き)を挟むと、余りが外へ押し出されて左右の端に寄ります。幅は本文幅の半分よりわずかに狭く、0.48\textwidth あたりが目安です。合計が \textwidth を超えると Overfull \hbox が出て二つ目が下へ落ちます。

latex
\begin{figure}[htbp]
  \centering
  \begin{minipage}{0.48\textwidth}
    \centering
    \includegraphics[width=\linewidth]{left}
    \caption{Left panel}      % its own number
    \label{fig:left}
  \end{minipage}
  \hfill
  \begin{minipage}{0.48\textwidth}
    \centering
    \includegraphics[width=\linewidth]{right}
    \caption{Right panel}     % a second, separate number
    \label{fig:right}
  \end{minipage}
\end{figure}

minipage の中では \linewidth がそのミニページの幅を指すので、\includegraphics[width=\linewidth] と書けば箱いっぱいに収まります。この例では minipage ごとに \caption を置いたので、二枚は 別々の番号 を持つ「図 1」「図 2」になります。一つの図の (a)(b) にしたいなら subcaption パッケージの出番で、その扱いは姉妹ページに譲ります。二段組で本文幅を越えて紙面いっぱいに広げたいなら figure*(表なら table*)を使いますが、前述のとおり置けるのはページ上端か専用ページだけです。

本文を図に回り込ませる — wrapfig

雑誌でよく見る「小さな図の脇に本文が回り込む」レイアウトには、wrapfig パッケージの wrapfigure 環境(表なら wraptable)を使います。これも Donald Arseneau の作で、placeins と同じ作者です。引数は四つ、うち必須は二つ。{r}どちら側に置くか、最後の {0.4\textwidth}図の幅 です。任意の [12] は回り込ませる 行数、任意の [34pt] は図を版面の外へどれだけ突き出すかの オーバーハング です。配置の文字は対になっていて、小文字はその場に固定、大文字はフロートとして動くことを許す という約束です。

latex
\usepackage{wrapfig}
% [lines]{side}[overhang]{width}
\begin{wrapfigure}[12]{r}[34pt]{0.4\textwidth}
  \centering
  \includegraphics[width=0.38\textwidth]{portrait}
  \caption{Portrait}
\end{wrapfigure}
文字備考
r / R小文字 r はその場に固定、大文字 R は浮動を許す
l / L小文字 l はその場に固定、大文字 L は浮動を許す
i / I内側(綴じ側)両面組版 twoside のときに左右ページで自動的に入れ替わる
o / O外側(小口側)両面組版 twoside のときに左右ページで自動的に入れ替わる

上の例では幅 0.4\textwidth の図が本文の に置かれ、続く 12 行 がその左を回り込み、[34pt] の分だけ右マージンへ突き出します。行数を省くと wrapfig が図の高さから見積もりますが、外れると回り込みが乱れるので、崩れたときは明示するのが早道です。ただし wrapfig は癖の強いパッケージで、マニュアル自身が使いどころを限定しています。

  • リストの中・直前・直後では使わない。 itemizeenumeratedescription の内部やその境目に置くと壊れます。
  • 改ページをまたがせない。 回り込みが二ページに割れない位置に置きます。ページの境目付近は避けてください。
  • 見出しや別行立ての数式を回り込ませない。 回り込むのは普通の本文だけにします。
  • 段落の途中ではなく、段落の切れ目で始める。 minipageparbox の中で使うときは、回り込みがそのグループの終わりより前で完結するようにします。

回り込みが乱れたときは、図の幅を少し狭める、行数を明示する、開始位置を一段落ずらす——このどれかでたいてい直ります。それでも整わないなら、wrapfig をやめて普通のフロート([htbp] で本文の上か下)に戻すほうが、結局は読みやすい紙面になることが多いものです。図の置き場所が決まったら、次はその図に番号と説明を与える番です。