データから表(CSV / 数値揃え)

表の中身が .csv ファイルなど 外部データ として既にあるなら、セルを一つずつ手で打ち込む必要はありません。LaTeX には CSV を読み込んで表に変換するパッケージがいくつもあり、データが変わってもソースを書き直さずに済みます。このページでは、手早い **csvsimple、整形に強い pgfplotstable、データベース的に扱う datatool の三つを使い分けとともに紹介し、最後に、数値を 小数点でそろえる** siunitxS 列に触れます(S 列の詳細は「単位(siunitx)」のページに譲ります)。

なぜデータから表を組むのか

実験結果や集計表は、表計算ソフトや測定機器から CSV(カンマ区切りの値) として出てくることがほとんどです。これを tabular のセルへ手作業で写すのは、退屈なうえに間違いのもと——データが一行増えるたび、桁が一つ変わるたびに、原稿に手を入れることになります。

考え方を変えて、データはデータファイルに置いたまま、LaTeX には「読み込んで組め」とだけ指示する ことができます。こうすれば、データを更新して再コンパイルするだけで表が追従します。元の CSV が一つあれば、本文・スライド・付録で同じ数値を何度でも使い回せ、転記ミスも起きません。この「データと体裁の分離」は、論理構造と見た目を分ける LaTeX の発想と地続きです。

このページの例では、次の小さな CSV ファイルを使います。一行目は 見出し行(ヘッダ) で、productpriceweight という列名が並び、二行目以降が中身です。

data.csv
product,price,weight
Apple,380,182.5
Orange,120,95.0
Melon,1280,1450.2

手早く読む — `csvsimple`

csvsimple は、CSV を読み込んで表や繰り返しを作る、軽快なパッケージです。\usepackage{csvsimple} で読み込みます(現行版は内部で LaTeX3 実装の csvsimple-l3 を選びます)。まず最も手軽なのが **\csvautotabular{data.csv}**。ファイル名を渡すだけで、CSV 全体を自動的に tabular に流し込み、一行目を見出しとして罫線つきで組んでくれます。中身をざっと表にしたいときに向きます。

latex
\csvautotabular{data.csv}

この一行で、productpriceweight を見出しとする 3 列・3 行の表ができます。手軽な反面、整形の自由度は限られます。**列の揃え方や罫線、列の取捨選択まで自分で決めたいなら \csvreader を使う** ——これが csvsimple の本命です。

\csvreader は三つの引数を取ります。\csvreader[オプション]{data.csv}{割り当て}{本体} の形です。第二引数 が読み込むファイル、第三引数 が「列名をマクロに結びつける割り当て」、第四引数 が「各行で出力する内容」。たとえば price=\price と書けば、見出し price の列の値が、本体の中で \price として使えるようになります。表の枠組みは tabular=table head=(見出し行)といったオプションで与えます。

latex
\csvreader[
  tabular = l r r,
  table head = \hline Product & Price & Weight \\ \hline,
  late after line = \\]
{data.csv}
{product=\product, price=\price, weight=\weight}
{\product & \price & \weight}

ここでは tabular = l r r で「左・右・右」の 3 列を宣言し、table head で見出し行と上の罫線を置き、本体 {\product & \price & \weight} が各データ行をセルに展開します。late after line = \\ は **各行の後に行末 \\ を補う** 指定です(行と行のあいだにだけ改行を入れ、最終行のあとには余計な改行を残さないための定石)。見出し名にスペースや記号が含まれる場合は、第三引数で番号を使う流儀もあり、\csvcoli\csvcolii\csvcoliii … が 1 列目・2 列目・3 列目 の中身を表します。

既定では一行目は 見出し として扱われ、データには含まれません。見出し行のない CSV を読むときは、星付きの \csvreader* を使うと一行目もデータ行として読まれます。csvsimple は他にも、条件で行を絞る filter、定義済みの割り当てを使い回す \csvstyle\csvnames など、表以外の繰り返し処理にも使える機能を備えています。

整形して読む — `pgfplotstable`

数値の 見せ方 まで作り込みたいなら、pgfplotstable が最も強力です。pgfplots の一部で、\usepackage{pgfplotstable} で読み込みます。中心となる命令は **\pgfplotstabletypeset[オプション]{data.csv}** ひとつ。これが CSV を読み、指定した桁数・数値形式に整え、内部で tabular を組み立てて出力します。CSV を読むときは区切り文字を col sep=comma で伝えます。

ふるまいは、すべて キー=値のオプション で制御します。代表的なものを挙げます。

オプション働き
col sep=commacol sep=commaCSV(カンマ区切り)として読む。既定は空白区切り
headerheader=has colnames / header=false一行目を列名として扱う / 見出しなしとして扱う
columnscolumns={a,b,...}出力する列とその順序を選ぶ
columns/NAME/.stylecolumns/price/.style={...}特定の列だけに書式を与える
column namecolumn name=見出しその列の見出し文字列を差し替える
fixedfixed, fixed zerofill, precision=n固定小数点・末尾ゼロ詰め・小数桁数 n
scisci, sci zerofill科学表記(指数形式)で組む
string typestring type文字列の列(数値整形をしない)
dec sep aligndec sep align列を小数点でそろえる(array が必要)
latex
\pgfplotstabletypeset[
  col sep = comma,
  header = has colnames,
  columns = {product, price, weight},
  columns/product/.style = {string type, column name = Product},
  columns/price/.style   = {column name = Price, fixed, precision = 0},
  columns/weight/.style  = {column name = Weight (g), fixed, fixed zerofill,
                            precision = 1, dec sep align},
]{data.csv}

この例では、product 列を string type(文字列)として、price 列を整数(precision=0)として、weight 列を小数 1 桁・末尾ゼロ詰めで組み、dec sep align で小数点をそろえています。見出しは column name でそれぞれ差し替えました。同じデータでも、precision を変えるだけで桁数が変わる ——数値の体裁を CSV と切り離して制御できるのが pgfplotstable の強みです。

さらに pgfplotstable は、読み込んだ列から 計算列 を作れます。create on use で「使うときに計算する列」を定義したり、columns/.../.style のなかで後処理(postproc cell content)を施したりと、表計算ソフトに近いことが LaTeX 内で完結します。罫線まわりは every head row/.stylebooktabs 連携(\toprule\midrule\bottomrule を自動で入れる設定)で整えられます。ここまで作り込めるぶん記法は重く、**「凝った数値表」には pgfplotstable、「素朴な CSV → 表」には csvsimple** という住み分けが目安です。

データベースとして扱う — `datatool`

三つめの datatool は、CSV を データベース として読み込み、行ごとの繰り返し処理(差し込み印刷のような処理)を得意とします。\usepackage{datatool} で読み込み、まず \DTLloaddb{名前}{data.csv} で CSV を名前付きのデータベースに取り込みます。既定では一行目が見出しとなり、その列名が各値の キー になります。見出しのない CSV は \DTLloaddb[noheader]{...}{...} とすると、列が Column1Column2 … と自動命名されます。

読み込んだら、**\DTLforeach{名前}{割り当て}{本体}** で各行を順に処理します。割り当ては \DTLforeach{db}{\Product=product,\Price=price}{…} のように「マクロ=列名」で書き、本体のなかで \Product\Price がその行の値に展開されます。表にするときは、tabular の中で \DTLforeach を回し、本体の末尾に行末 \\ を置きます。

latex
\DTLloaddb{goods}{data.csv}

\begin{tabular}{l r}
  \hline
  Product & Price \\
  \hline
  \DTLforeach{goods}{\Product=product, \Price=price}{%
    \Product & \Price \\}
  \hline
\end{tabular}

この例では goods という名前で CSV を読み込み、tabular の中で \DTLforeach が行ごとに「商品名 & 価格」を出力します。datatool の真価は単なる表組みより データ操作 にあります——数値の合計・平均、並べ替え、条件による行の除外などをマクロで行え、文献リストや差し込み文書の生成にも使われます。逆に、ただ CSV を表にするだけなら csvsimple のほうが簡潔です。

数値を小数点でそろえる — siunitx の `S` 列

データの出どころが CSV であってもなくても、数値を並べた列は 桁をそろえないと読みにくい という問題は共通です。手で打った tabular でこれを解決する定番が、siunitx の **S 列** です。列指定で r などの代わりに S と書くと、その列の数値が 小数点の位置で整列 します。\usepackage{siunitx} を読み込めば使えます。

latex
\begin{tabular}{l S[table-format=4.1]}
  \toprule
  {Product} & {Weight / \unit{\gram}} \\
  \midrule
  Apple  &  182.5 \\
  Orange &   95.0 \\
  Melon  & 1450.2 \\
  \bottomrule
\end{tabular}

この例では、2 列目を S[table-format=4.1] として「整数 4 桁・小数 1 桁」で組み、182.595.01450.2 を小数点でそろえています。二つの要点 があります。一つは table-format=整数桁.小数桁列中で最も大きな値に合わせて 指定すること。もう一つは、**列見出しのような文字列は波括弧 {…} で囲んで保護** することです({Weight / \unit{\gram}})。保護を忘れると siunitx が見出しを数値として解釈しようとし、整列が崩れます。

S 列の詳しい使い方——table-format の指定、文字列の保護、\multicolumn 内で使えるマクロ版 \tablenum、指数つきの値の扱いなど——は「単位(siunitx)」のページで扱っています。本文の量は \qty、表の中の数値は S 列、と役割を分けると、文書全体で数値表記が一貫します。

どれを使うか

目的に応じて使い分けるのが一番です。おおよその指針は次のとおり。

  • 素朴な CSV → 表 なら csvsimple\csvautotabular で即席、\csvreader で列の揃えや罫線まで制御。
  • 数値の桁数・形式を作り込む/計算列が要る なら pgfplotstable。最も強力だが記法は重め。
  • 集計・並べ替え・条件処理などデータ操作 が主目的なら datatool。差し込み文書にも。
  • 列内の数値を小数点でそろえたい だけなら siunitxS 列。手書きの tabular にそのまま使える。

いずれの方法でも、土台になるのは tabular の列指定・&\\・罫線という共通の約束ごとです。まず「tabular の基本」を押さえたうえで、データの量と整形の要求に合わせて道具を選ぶとよいでしょう。