Pythonライブラリ `tabulate` 詳細解説:ターミナルやレポートで見やすい表を作成しよう!

Pythonを使ってデータを扱う際、リストや辞書、あるいはPandas DataFrameなどの形式でデータを持つことは多いでしょう。これらのデータをそのまま表示すると、特にデータ量が多い場合やターミナルでの確認時には、非常に見づらくなってしまうことがあります。そんなときに活躍するのが、Pythonライブラリの tabulate です。

tabulate は、様々な形式の表形式データを、人間に読みやすいプレーンテキストの表(テーブル)や、HTML、Markdown、LaTeXなどの形式で簡単に出力できる非常に便利なライブラリです。コマンドラインインターフェース(CLI)でのデータ表示、Jupyter Notebookでの結果表示、簡単なレポート作成など、多岐にわたる場面で役立ちます。今回は、この tabulate の基本的な使い方から、応用的な機能までを詳しく解説していきます。

インストール

tabulate ライブラリは、Pythonの標準ライブラリではないため、別途インストールが必要です。pipコマンドを使って簡単にインストールできます。ターミナル(またはコマンドプロンプト)で以下のコマンドを実行してください。

pip install tabulate

特定のユーザーのみにインストールしたい場合は --user オプションを追加します。

pip install tabulate --user

また、日本語のような全角文字(ワイドキャラクター)を含む表を正しく扱うためには、wcwidth ライブラリが追加で必要になる場合があります。以下のコマンドで tabulate と一緒にインストールできます。

pip install tabulate[widechars]

wcwidth がインストールされていれば、全角文字のサポートは自動的に有効になります。

基本的な使い方

tabulate の基本的な使い方は非常にシンプルです。メインとなる tabulate() 関数に、表にしたいデータと、必要に応じてヘッダー情報を渡すだけです。

リストのリスト (List of Lists)

最も基本的なデータ形式は、リストのリスト(あるいはタプルのリストなど、イテラブルのイテラブル)です。

from tabulate import tabulate
# サンプルデータ(リストのリスト)
data = [ ["太陽", 696000, 1989100000], ["地球", 6371, 5973.6], ["月", 1737, 73.5], ["火星", 3390, 641.85]
]
# ヘッダー情報
headers = ["天体名", "半径 (km)", "質量 (x 10^21 kg)"]
# 表形式で出力
print(tabulate(data, headers=headers))

これを実行すると、以下のような整形された表が標準出力に表示されます。

天体名 半径 (km) 質量 (x 10^21 kg)
-------- ----------- -------------------
太陽 696000 1.9891e+09
地球 6371 5973.6
月 1737 73.5
火星 3390 641.85

headers 引数を指定しない場合は、ヘッダーなしの表が出力されます。また、headers="firstrow" と指定すると、データの最初の行がヘッダーとして使用されます。

data_with_header = [ ["天体名", "半径 (km)", "質量 (x 10^21 kg)"], ["太陽", 696000, 1989100000], ["地球", 6371, 5973.6], ["月", 1737, 73.5], ["火星", 3390, 641.85]
]
print(tabulate(data_with_header, headers="firstrow"))

出力結果:

天体名 半径 (km) 質量 (x 10^21 kg)
-------- ----------- -------------------
太陽 696000 1.9891e+09
地球 6371 5973.6
月 1737 73.5
火星 3390 641.85

辞書のリスト (List of Dictionaries)

辞書のリスト形式のデータも扱うことができます。この場合、デフォルトでは辞書のキーがヘッダーとして使用されます。

from tabulate import tabulate
data_dict_list = [ {'天体名': '太陽', '半径 (km)': 696000, '質量 (x 10^21 kg)': 1989100000}, {'天体名': '地球', '半径 (km)': 6371, '質量 (x 10^21 kg)': 5973.6}, {'天体名': '月', '半径 (km)': 1737, '質量 (x 10^21 kg)': 73.5}, {'天体名': '火星', '半径 (km)': 3390, '質量 (x 10^21 kg)': 641.85}
]
# headers="keys" はデフォルトなので省略可能
print(tabulate(data_dict_list, headers="keys"))

出力結果:

天体名 半径 (km) 質量 (x 10^21 kg)
-------- ----------- -------------------
太陽 696000 1.9891e+09
地球 6371 5973.6
月 1737 73.5
火星 3390 641.85

その他のデータ形式

tabulate は、他にも以下のデータ形式をサポートしています。

  • 辞書のイテラブル(キーがカラム名)
  • 2次元 NumPy 配列
  • NumPy レコード配列(フィールド名がカラム名)
  • pandas DataFrame
  • リストやイテラブルの dataclass (Python 3.7+)

特に pandas DataFrame との連携は強力です。

import pandas as pd
from tabulate import tabulate
# pandas DataFrame の作成
df = pd.DataFrame(data_dict_list)
# DataFrame を tabulate で表示 (インデックスは表示しない)
print(tabulate(df, headers='keys', tablefmt='psql', showindex=False))

出力結果 (psql フォーマット):

+----------+-------------+-----------------------+
| 天体名 | 半径 (km) | 質量 (x 10^21 kg) |
|----------+-------------+-----------------------|
| 太陽 | 696000 | 1.9891e+09 |
| 地球 | 6371 | 5973.6 |
| 月 | 1737 | 73.5 |
| 火星 | 3390 | 641.85 |
+----------+-------------+-----------------------+

showindex=False で DataFrame のインデックスを非表示にしています。代わりに showindex="always" とすると、常にインデックスが表示されます。

テーブルフォーマット (tablefmt)

tabulate の大きな特徴の一つが、豊富な出力フォーマットをサポートしている点です。tabulate() 関数の tablefmt 引数で、出力する表のスタイルを指定できます。

以下にいくつかの代表的なフォーマットと、その出力例を示します。(データは前述のリストのリストを使用)

plain (デフォルトに近いシンプルな形式)

print(tabulate(data, headers=headers, tablefmt="plain"))
天体名 半径 (km) 質量 (x 10^21 kg)
太陽 696000 1.9891e+09
地球 6371 5973.6
月 1737 73.5
火星 3390 641.85

simple (Pandoc simple_tables 形式)

print(tabulate(data, headers=headers, tablefmt="simple"))
天体名 半径 (km) 質量 (x 10^21 kg)
-------- ----------- -------------------
太陽 696000 1.9891e+09
地球 6371 5973.6
月 1737 73.5
火星 3390 641.85

github (GitHub Flavored Markdown 形式)

print(tabulate(data, headers=headers, tablefmt="github"))
| 天体名 | 半径 (km) | 質量 (x 10^21 kg) |
|----------|-------------|---------------------|
| 太陽 | 696000 | 1.9891e+09 |
| 地球 | 6371 | 5973.6 |
| 月 | 1737 | 73.5 |
| 火星 | 3390 | 641.85 |

この形式は、GitHubのMarkdownファイルやQiitaなどのサービスで表を記述する際に便利です。

grid (罫線で囲まれた形式)

print(tabulate(data, headers=headers, tablefmt="grid"))
+----------+-------------+-----------------------+
| 天体名 | 半径 (km) | 質量 (x 10^21 kg) |
+==========+=============+=======================+
| 太陽 | 696000 | 1.9891e+09 |
+----------+-------------+-----------------------+
| 地球 | 6371 | 5973.6 |
+----------+-------------+-----------------------+
| 月 | 1737 | 73.5 |
+----------+-------------+-----------------------+
| 火星 | 3390 | 641.85 |
+----------+-------------+-----------------------+

fancy_grid (grid より少し装飾的な罫線)

print(tabulate(data, headers=headers, tablefmt="fancy_grid"))
╒══════════╤═════════════╤═══════════════════════╕
│ 天体名 │ 半径 (km) │ 質量 (x 10^21 kg) │
╞══════════╪═════════════╪═══════════════════════╡
│ 太陽 │ 696000 │ 1.9891e+09 │
├──────────┼─────────────┼───────────────────────┤
│ 地球 │ 6371 │ 5973.6 │
├──────────┼─────────────┼───────────────────────┤
│ 月 │ 1737 │ 73.5 │
├──────────┼─────────────┼───────────────────────┤
│ 火星 │ 3390 │ 641.85 │
╘══════════╧═════════════╧═══════════════════════╛

pipe (PHP Markdown Extra 形式)

print(tabulate(data, headers=headers, tablefmt="pipe"))
| 天体名 | 半径 (km) | 質量 (x 10^21 kg) |
|:---------|------------:|--------------------:|
| 太陽 | 696000 | 1.9891e+09 |
| 地球 | 6371 | 5973.6 |
| 月 | 1737 | 73.5 |
| 火星 | 3390 | 641.85 |

html (HTML 形式)

print(tabulate(data, headers=headers, tablefmt="html"))

出力されるHTMLは以下のようになります(整形済み)。このブログのようにBulmaなどのCSSフレームワークと組み合わせると、簡単に見栄えの良い表をWebページに埋め込めます。

天体名 半径 (km) 質量 (x 10^21 kg)
太陽 696000 1.9891e+09
地球 6371 5973.6
1737 73.5
火星 3390 641.85

これら以外にも、latex, latex_raw, latex_booktabs, rst, mediawiki, jira, tsv など、多数のフォーマットがサポートされています。レポート作成、ドキュメント生成、Wikiへの貼り付けなど、用途に応じて最適なフォーマットを選択できます。

利用可能なフォーマットの一覧は、tabulate.tabulate_formats で確認できます。

from tabulate import tabulate_formats
print(tabulate_formats)

アライメント(配置)の調整

tabulate は賢く、列の内容に応じて自動的にアライメント(テキストの配置)を調整してくれます。デフォルトでは、数値データ(整数や浮動小数点数)は右寄せ(小数点がある場合は小数点基準)、それ以外のテキストデータは左寄せになります。

このデフォルトの挙動は、numalign(数値)と stralign(文字列)引数で変更できます。指定できる値は "right", "center", "left" です。数値の場合のみ "decimal" (小数点揃え)も指定可能です。None を指定するとアライメントが無効になります。

全体の数値・文字列アライメントを変更

from tabulate import tabulate
data = [ ["Alice", 24, 1200.50], ["Bob", 30, 850.75], ["Charlie", 22, 2100.00]
]
headers = ["名前", "年齢", "給与"]
# 数値を左寄せ、文字列を中央寄せにする
print(tabulate(data, headers=headers, numalign="left", stralign="center", tablefmt="grid"))

出力結果:

+---------+--------+--------+
| 名前 | 年齢 | 給与 |
+=========+========+========+
| Alice | 24 | 1200.5 |
+---------+--------+--------+
| Bob | 30 | 850.75 |
+---------+--------+--------+
| Charlie | 22 | 2100.0 |
+---------+--------+--------+

列ごとにアライメントを指定 (colalign)

さらに細かく、列ごとにアライメントを指定したい場合は colalign 引数を使用します。この引数には、各列のアライメント設定をタプルまたはリストで渡します。

from tabulate import tabulate
data = [ ["Alice", 24, 1200.50], ["Bob", 30, 850.75], ["Charlie", 22, 2100.00]
]
headers = ["名前", "年齢", "給与"]
# 1列目: 左寄せ, 2列目: 中央寄せ, 3列目: 右寄せ
print(tabulate(data, headers=headers, colalign=("left", "center", "right"), tablefmt="grid"))

出力結果:

+---------+--------+--------+
| 名前 | 年齢 | 給与 |
+=========+========+========+
| Alice | 24 | 1200.5 |
+---------+--------+--------+
| Bob | 30 | 850.75 |
+---------+--------+--------+
| Charlie | 22 | 2100.0 |
+---------+--------+--------+

このように、colalign を使うことで、データの種類や見せたい意図に合わせて、より柔軟なアライメント調整が可能です。

注意点として、tabulate は数値を自動で認識しようとしますが、この処理を無効にしたい場合は disable_numparse=True を指定します。

数値フォーマット (floatfmt, intfmt)

小数点を含む数値(浮動小数点数)や整数の表示形式もカスタマイズできます。

浮動小数点数のフォーマット (floatfmt)

floatfmt 引数を使うと、浮動小数点数の表示形式を Python の標準的なフォーマット指定文字列(例: ".2f" で小数点以下2桁表示)や、より高度な指定方法で制御できます。

from tabulate import tabulate
data = [ ["Item A", 12.3456, 0.987], ["Item B", 1234.5, 0.1], ["Item C", 1.2, 0.005]
]
headers = ["商品名", "価格", "割引率"]
# 価格は小数点以下2桁、割引率はパーセント表示 (小数点以下1桁)
print(tabulate(data, headers=headers, floatfmt=(".2f", ".1%"), tablefmt="pipe"))

出力結果:

| 商品名 | 価格 | 割引率 |
|:---------|-------:|---------:|
| Item A | 12.35 | 98.7% |
| Item B | 1234.50 | 10.0% |
| Item C | 1.20 | 0.5% |

floatfmt にタプルやリストを渡すことで、列ごとに異なるフォーマットを指定できます。

整数のフォーマット (intfmt)

同様に intfmt 引数で整数の表示形式を指定できます。例えば、桁区切りカンマを入れるなどが可能です。

from tabulate import tabulate
data = [ ["Population", 123456789, 9876543], ["Area (sq km)", 377975, 10000]
]
headers = ["項目", "日本", "東京"]
# 整数にカンマ区切りを入れる
print(tabulate(data, headers=headers, intfmt=",", tablefmt="grid"))

出力結果:

+----------------+-------------+----------+
| 項目 | 日本 | 東京 |
+================+=============+==========+
| Population | 123,456,789 | 9,876,543|
+----------------+-------------+----------+
| Area (sq km) | 377,975 | 10,000 |
+----------------+-------------+----------+

欠損値の表示 (missingval)

データ中に None が含まれる場合、デフォルトでは空欄として表示されますが、missingval 引数で表示する文字列を指定できます。

from tabulate import tabulate
data = [ ["Alice", 24, 1200.50], ["Bob", None, 850.75], # 年齢が欠損 ["Charlie", 22, None] # 給与が欠損
]
headers = ["名前", "年齢", "給与"]
print(tabulate(data, headers=headers, missingval="N/A", tablefmt="simple"))

出力結果:

名前 年齢 給与
--------- ------ ------
Alice 24 1200.5
Bob N/A 850.75
Charlie 22 N/A

長いテキストの折り返し (maxcolwidths)

テーブルのセルに含まれるテキストが非常に長い場合、表全体の幅が広がりすぎて見にくくなることがあります。tabulate では maxcolwidths 引数を使って、列の最大幅を指定し、それを超えるテキストを自動的に折り返す(改行する)機能があります。

maxcolwidths には、各列の最大幅を整数で指定したリストまたはタプルを渡します。すべての列に同じ最大幅を適用したい場合は、単一の整数を渡すこともできます。特定の列に最大幅を設定したくない場合は、リスト/タプル内でその列に対応する要素を None にします。

テキストの折り返し処理には、Python の標準ライブラリ textwrap が内部で使用されます。

from tabulate import tabulate
data = [ [1, "非常に長い説明文が入ります。このテキストは指定された幅を超えると自動的に折り返されます。", 100], [2, "短い説明文", 200], [3, "こちらもかなり長い説明文です。改行されて見やすくなるはずです。", 150]
]
headers = ["ID", "説明", "値"]
# 2列目の最大幅を30文字に設定
print(tabulate(data, headers=headers, maxcolwidths=[None, 30, None], tablefmt="grid"))

出力結果:

+------+--------------------------------+-------+
| ID | 説明 | 値 |
+======+================================+=======+
| 1 | 非常に長い説明文が入ります。 | 100 |
| | このテキストは指定された幅を超 | |
| |えると自動的に折り返されます。 | |
+------+--------------------------------+-------+
| 2 | 短い説明文 | 200 |
+------+--------------------------------+-------+
| 3 | こちらもかなり長い説明文です。 | 150 |
| | 改行されて見やすくなるはずです。| |
+------+--------------------------------+-------+

このように、maxcolwidths を使うことで、長いテキストを含む表でも、レイアウト崩れを防ぎ、読みやすさを保つことができます。

活用例

tabulate は様々な場面で役立ちます。

  • コマンドラインツール(CLI)での出力: スクリプトの実行結果を整形して表示する際に非常に便利です。
  • Jupyter Notebook/Lab: データ分析の過程や結果をノートブック上で分かりやすく表示できます。特にHTMLフォーマットはインタラクティブな環境と相性が良いです。
  • 簡単なレポート生成: Markdown や LaTeX フォーマットで出力すれば、そのままレポートやドキュメントに組み込めます。
  • デバッグ時のデータ確認: 複雑なデータ構造の中身を一時的に確認したい場合にも、手軽に整形された表形式で表示できるため役立ちます。
  • Webアプリケーション: HTMLフォーマットで出力し、Webフレームワーク (Flask, Djangoなど) のテンプレートに埋め込むことで、動的にテーブルを生成できます。

例えば、2025年1月に公開されたZennの記事では、複数のExcelファイルを読み込み、その内容を tabulate を使ってMarkdown形式に変換し、一つのファイルにまとめることで、生成AIでの解析を容易にするという活用例が紹介されていました。これにより、大量の表データをAIに効率的に入力し、要約や洞察を得ることが可能になります。

まとめ

tabulate は、Pythonで表形式データを扱う際に、驚くほど簡単に、そして柔軟に見栄えの良いテーブルを作成できる強力なライブラリです。たった1つの関数 tabulate() を覚えるだけで、様々なデータソースと出力フォーマットに対応でき、アライメントや数値フォーマットの調整も可能です。

日々の開発作業やデータ分析において、結果を見やすく表示したい、あるいは簡単なレポートを作成したいといったニーズは頻繁に発生します。tabulate を活用することで、これらの作業を効率化し、より質の高いアウトプットを生み出す手助けとなるでしょう。ぜひ、あなたのPythonプロジェクトに取り入れてみてください!