データをprettytableで簡単に表形式で出力してみよう
PrettyTable について
PrettyTableは、データをASCII文字で表形式で出力することがための拡張ライブラリです。 これは、PostgreSQL のコマンドラインツール psql の出力で使用されるASCIIテーブルに触発されて開発されています。
機能としては次のものがあります。
出力のスタイルを制御
列のパディングの幅、テキストの配置、テーブルの境界線など、テーブル表示のさまざまな制御を行うことができます。
データを並べ替える
出力データの選択:データの列と行を選択することができる
複数のデータソースをサポート
CSV、HTML、またはデータベースカーソルからデータを読み取ることができる
複数の出力フォーマットをサポート
ASCIIの他にHTMLで出力することができる
PrettyTable のインストール
PrettyTable は拡張モジュールなのでインストールする必要が’ありまうす。
code: zsh
% pip install prettytable
使用方法
テーブルを作成するためには、はじめにPrettyTable()クラスのインスタンスを生成します。
add_row()メソッド
PrettyTable()クラスのコンストラクタで field_namesにヘッダ行として表示するフィールド名のリストあるいはタプルを与えてインスタンスを作成します。
次に、add_row()メソッドで行を追加していく方法でテーブルを作成します。
code: prettyprint_add_row.py
from prettytable import PrettyTable
data = [
]
table = PrettyTable(field_names=data0) table.add_row(row_data)
print(table) # print(table.get_string()) と同じ
生成したPrettyTableインスタンスをprint()に与えるとASCII文字でテーブルを出力します。
これは、get_string()メソッドを呼び出していることと等価です。
code: zsh
% python prettytable_add_row.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
この例で使用している add_row() メソッドは、1つの引数を受け取ることができます。追加する行データを含むリストまたはタプルです。
add_column()メソッド
add_row()メソッドで行を追加していく方法でテーブルを作成します。
この場合は、PrettyTableクラスのコンストラクタに引数は不要です。
code: prettytable_add_cloumn.py
from prettytable import PrettyTable
data = {
'City name': [ 'Adelaide', 'Brisbane', 'Darwin',
'Hobart', 'Melbourne', 'Perth', 'Sydney'],
'Population': [1158259, 1857594, 120900,
205556, 3806092, 1554769, 4336374],
}
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
print(table)
この例で使用している add_column() メソッドは、2つの引数を受け取ることができます。追加する列が対応するフィールドの名前である文字列と、列データを含むリストまたはタプルです。
テーブル出力したいデータをdict型で保持しているときに向いている方法です。
code: zsh
% python prettytable_add_column.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
カラムを指定したソート
PrettyTableはカラムを指定してソートすることができます。
デフォルトでは昇順でソートされますが、get_string(reversesort=True) とすると降順でソートされます。つまり、reversesort=False がデフォルト値というわけです。
dict型のデータ data があるとします。
code: data.py
data = {
'City name': [ 'Adelaide', 'Brisbane', 'Darwin',
'Hobart', 'Melbourne', 'Perth', 'Sydney'],
'Population': [1158259, 1857594, 120900,
205556, 3806092, 1554769, 4336374],
}
code: prettytable_sorted.py
from prettytable import PrettyTable
from data import data
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
table.sortby = 'Area'
print(table)
table.sortby = 'Population'
print(table.get_string(reversesort=True))
code:zsh
% python prettytable_sorted.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Darwin | 112 | 120900 | 1714.7 |
| Adelaide | 1295 | 1158259 | 600.5 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Sydney | 2058 | 4336374 | 1214.8 |
| Perth | 5386 | 1554769 | 869.4 |
| Brisbane | 5905 | 1857594 | 1146.4 |
+-----------+------+------------+-----------------+
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Sydney | 2058 | 4336374 | 1214.8 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Perth | 5386 | 1554769 | 869.4 |
| Adelaide | 1295 | 1158259 | 600.5 |
| Hobart | 1357 | 205556 | 619.5 |
| Darwin | 112 | 120900 | 1714.7 |
+-----------+------+------------+-----------------+
テーブルの部分出力
PrettyTableはカラムや行を指定して出力することができます。
code: prettytable_select.py
from prettytable import PrettyTable
from data import data
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
print(table.get_string(start=2, end=5))
code: zsh
% python prettytable_select.py
+-----------+------+
| City name | Area |
+-----------+------+
| Adelaide | 1295 |
| Brisbane | 5905 |
| Darwin | 112 |
| Hobart | 1357 |
| Melbourne | 1566 |
| Perth | 5386 |
| Sydney | 2058 |
+-----------+------+
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
+-----------+------+------------+-----------------+
+-----------+------------+
| City name | Population |
+-----------+------------+
| Darwin | 120900 |
| Hobart | 205556 |
| Melbourne | 3806092 |
+-----------+------------+
行や列の削除
PrettyTableオブジェクトには、テーブルの行や列を削除することもできる、次のメソッドが提供されています。
del_row():インデックスで指定した1行を削除する
del_column():フィールド名で与えた列を削除する
clear_rows():引数不要、テーブル内のすべての行を削除する
ヘッダ(フィールド名)はそのままに残り、同じ種類のデータを再入力するときに使用
clear():引数不要、すべての行とヘッダ(すべてのフィールド名)を削除する
後述するスタイル関連の設定は残る
code: prettytable_delete.py
from prettytable import PrettyTable
from data import data
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
print(table)
table.del_row(0)
table.del_column("Annual Rainfall")
print(table)
code: zsh
% python prettytable_delete.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
+-----------+------+------------+
| City name | Area | Population |
+-----------+------+------------+
| Brisbane | 5905 | 1857594 |
| Darwin | 112 | 120900 |
| Hobart | 1357 | 205556 |
| Melbourne | 1566 | 3806092 |
| Perth | 5386 | 1554769 |
| Sydney | 2058 | 4336374 |
+-----------+------+------------+
code: prettytable_clear.py
from prettytable import PrettyTable
from data import data
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
print(table)
table.clear_rows()
print(table)
code: zsh
% python prettytable_clear.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
+-----------+------+------------+-----------------+
PrettyTable クラスのアトリビュート
PrettyTableクラスオブジェクトのアトリビュートのうちで、主なものを説明します。
title:テーブルのタイトル
field_names:ヘッダのフィールド名 リストもしくはタプル
start:表示開始の行
end:表示終了の行
header:Falseでヘッダを表示しない (デフォルトはTrue)
header_style:ヘッダの表示すたいる(デフォルトはNone)
"cap":各単語の最初の文字を大文字に
"title":タイトルケース
"upper":すべて大文字
"lower":すべて小文字
None:元のフィールド名のまま
border:Falseで枠線/境界線を表示しない (デフォルトはTrue)
padding_width:列データの左右の空白文字の数。
left_padding_widthとright_padding_widthが設定されていないときだけ有効
left_padding_width:列データの左側の空白文字の数
right_padding_width:列データの右側の空白文字の数
alignment:水平方向の配置 左(l)、右(r)、中央(c)、None
valign:垂直方向の配置 上(t)、中央(m)、下(b)
hrules:行の印刷ルールを制御 FRAME、ALL、NONE
モジュールで定義された値:prettytable.FRAME
vrules:列の印刷ルールを制御 FRAME、ALL、NONE
モジュールで定義された値:prettytable.FRAME
min_table_width:最小テーブル幅(文字数)
max_table_width:最大テーブル幅(文字数)
int_format:整数値の表示幅 %演算子 %Nd のときのNを与える
float_format:整数値の表示幅 %演算子 %Nf のときのNを与える
vertical_char:垂直線の描画に使用される単一の文字。デフォルトは |
horizontal_char-水平線の描画に使用される単一の文字。デフォルトは-
junction_char-ラインノットの描画に使用される単一の文字。デフォルト+
sortby:ソートを行う列のフィールド名
sort_key :ソートを行う関数
スタイル
set_style()に以下の値を与えます。
MSWORD_FRIENDLY/MARKDOWN:ワードやMARKDOWNに向いた出力
DEFAULT:デフォルトの外観。スタイルの変更を元に戻すために使用する
PLAIN_COLUMNS:枠線がないスタイル、コマンドラインプログラムでの出力に向いている
code: prettytable_style.py
from prettytable import PrettyTable, MARKDOWN, PLAIN_COLUMNS, DEFAULT
from data import data
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
print('DEFAULT style ---------')
table.set_style(DEFAULT)
print(table)
print('\nMARKDOWN style ---------')
table.set_style(MARKDOWN)
print(table)
print('\nPLAIN_COLUMNS style ---------')
table.set_style(PLAIN_COLUMNS)
print(table)
code: zsh
DEFAULT style ---------
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
MARKDOWN style ---------
| City name | Area | Population | Annual Rainfall |
|-----------|------|------------|-----------------|
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
PLAIN_COLUMNS style ---------
City name Area Population Annual Rainfall
Adelaide 1295 1158259 600.5
Brisbane 5905 1857594 1146.4
Darwin 112 120900 1714.7
Hobart 1357 205556 619.5
Melbourne 1566 3806092 646.9
Perth 5386 1554769 869.4
Sydney 2058 4336374 1214.8
ヘッダ、ボーダー、パディング
header、border、padding_wdth を与えるとデータだけを表示します。
code: prettytable_padding.py
from prettytable import PrettyTable
from data import data
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
table.header = False
table.border = False
table.padding_width = 6
print(table)
code: zsh
% python prettytable_padding.py
Adelaide 1295 1158259 600.5
Brisbane 5905 1857594 1146.4
Darwin 112 120900 1714.7
Hobart 1357 205556 619.5
Melbourne 1566 3806092 646.9
Perth 5386 1554769 869.4
Sydney 2058 4336374 1214.8
左寄せ、右寄せ、センタリング
PrettyTableオブジェクトのalignmentアトリビュートを設定することで、左寄せ(l)、右寄せ(r)、センタリング(c)の指定ができます。
code: prettytable_alignment.py
from prettytable import PrettyTable
from data import data
table = PrettyTable()
for key, val in data.items():
table.add_column(key, val)
print(table)
code: zsh
% python prettytable_alignment.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
出力フォーマット
PrettyTable では次のフォーマットでデータを出力することができます。
get_string(): ASCII文字を出力する (デフォルトのスタイル)
get_csv_string():CSVフォーマットで出力する
get_json_string():JSONフォーマットで出力する
get_heml_string():HTML形式で出力する
簡単なフォーマット変換ツールとしても使えることになります。
特にHTML出力は、Flask などのWebアプリケーションフレームワークからでも利用できるので便利ですね。
code: zsh
In 1: %run prettytable_add_row.py +-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
In 2: print(table.get_csv_string()) City name,Area,Population,Annual Rainfall
Adelaide,1295,1158259,600.5
Brisbane,5905,1857594,1146.4
Darwin,112,120900,1714.7
Hobart,1357,205556,619.5
Melbourne,1566,3806092,646.9
Perth,5386,1554769,869.4
Sydney,2058,4336374,1214.8
In 3: print(table.get_json_string()) [
[
"City name",
"Area",
"Population",
"Annual Rainfall"
],
(中略)
{
"Annual Rainfall": 1214.8,
"Area": 2058,
"City name": "Sydney",
"Population": 4336374
}
]
In 4: print(table.get_html_string()) <table>
<thead>
<tr>
<th>City name</th>
<th>Area</th>
<th>Population</th>
<th>Annual Rainfall</th>
</tr>
</thead>
<tbody>
<tr>
(中略)
<tr>
<td>Sydney</td>
<td>2058</td>
<td>4336374</td>
<td>1214.8</td>
</tr>
</tbody>
</table>
データソース
prettytable では複数のデータソースをサポートしています。
from_csv():CSVファイルからデータを取り込む
from_db_cursor():SQL文でのクエリ結果からデータを取り込む
from_json():JSONデータからデータを取り込む
from_html_one():HTMLデータから表のデータを取り込む
from_html():HTMLデータから指定した表のデータを取り込む
CSVファイルからデータを取り込む
次のCSVファイルからデータを読み込んでみましょう。
code: CITY.csv
City name,Area,Population,Annual Rainfall
Adelaide, 1295, 1158259, 600.5
Brisbane, 5905, 1857594, 1146.4
Darwin, 112, 120900, 1714.7
Hobart, 1357, 205556, 619.5
Melbourne, 1566, 3806092, 646.9
Perth, 5386, 1554769, 869.4
Sydney, 2058, 4336374, 1214.8
code: prettytable_csv.py
from prettytable import from_csv
with open("CITY.csv") as fp:
table = from_csv(fp)
print(table)
code: zsh
% python prettytable_csv.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Adelaide | 1295 | 1158259 | 600.5 |
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
データーベース・カーソルからデータを取り込む
例示のために、まず、先の CITY.csv から SQLite3 のデータベースを作成してみます。
code: csv2db.py
import sqlite3
import pandas as pd
def readcsv(filename):
df = pd.read_csv(filename)
df.columns = df.columns.str.replace(' ', '_')
return df
def writedb(df, filename):
conn = sqlite3.connect(filename)
table_name = filename.split('.')0 df.to_sql(table_name, conn, if_exists='replace')
conn.commit()
conn.close()
if __name__ == '__main__':
import typer
def cli(csvfile: str = typer.Argument(...),
dbfile: str = typer.Argument(...),
):
data = readcsv(csvfile)
writedb(data, dbfile)
typer.run(cli)
code: zsh
% python csv2db.py CITY.csv CITY.db
これで、データベース CITY.db が作成されました。
code: zsh
% sqlite3 CITY.db
SQLite version 3.33.0 2020-08-14 13:23:32
Enter ".help" for usage hints.
sqlite> .tables
CITY
sqlite> .schema
CREATE TABLE IF NOT EXISTS "CITY" (
"index" INTEGER,
"City name" TEXT,
"Area" INTEGER,
" Population" INTEGER,
" Annual Rainfall" REAL
);
CREATE INDEX "ix_CITY_index"ON "CITY" ("index");
sqlite>
データベースからSQL文のクエリ結果が格納された cursorからデータを抽出することができます。
code: prettytable_db.py
import sqlite3
from prettytable import from_db_cursor
connection = sqlite3.connect("CITY.db")
cursor = connection.cursor()
cursor.execute("SELECT * FROM CITY")
table = from_db_cursor(cursor)
print(table)
code: zsh
% python prettytable_db.py
+-------+-----------+------+------------+-----------------+
| index | City_name | Area | Population | Annual_Rainfall |
+-------+-----------+------+------------+-----------------+
| 0 | Adelaide | 1295 | 1158259 | 600.5 |
| 1 | Brisbane | 5905 | 1857594 | 1146.4 |
| 2 | Darwin | 112 | 120900 | 1714.7 |
| 3 | Hobart | 1357 | 205556 | 619.5 |
| 4 | Melbourne | 1566 | 3806092 | 646.9 |
| 5 | Perth | 5386 | 1554769 | 869.4 |
| 6 | Sydney | 2058 | 4336374 | 1214.8 |
+-------+-----------+------+------------+-----------------+
JSONファイルからデータを取り込む
今次のJSONファイルがあるとします。(print(table.get_json_string())で出力したものと同じ)
code: CITY.json
[
{
"City name": "Adelaide",
"Area": 1295,
"Population": 1158259,
"Annual Rainfall": 600.5
},
{
"City name": "Brisbane",
"Area": 5905,
"Population": 1857594,
"Annual Rainfall": 1146.4
},
{
"City name": "Darwin",
"Area": 112,
"Population": 120900,
"Annual Rainfall": 1714.7
},
{
"City name": "Hobart",
"Area": 1357,
"Population": 205556,
"Annual Rainfall": 619.5
},
{
"City name": "Melbourne",
"Area": 1566,
"Population": 3806092,
"Annual Rainfall": 646.9
},
{
"City name": "Perth",
"Area": 5386,
"Population": 1554769,
"Annual Rainfall": 869.4
},
{
"City name": "Sydney",
"Area": 2058,
"Population": 4336374,
"Annual Rainfall": 1214.8
}
]
code: prettytable_json.py
from prettytable import from_json
with open('CITY.json') as fp:
json_data = fp.read()
table = from_json(json_data)
print(table)
code: zsh
% python prettytable_json.py
+-----------+------+------------+-----------------+
| City name | Area | Population | Annual Rainfall |
+-----------+------+------------+-----------------+
| Brisbane | 5905 | 1857594 | 1146.4 |
| Darwin | 112 | 120900 | 1714.7 |
| Hobart | 1357 | 205556 | 619.5 |
| Melbourne | 1566 | 3806092 | 646.9 |
| Perth | 5386 | 1554769 | 869.4 |
| Sydney | 2058 | 4336374 | 1214.8 |
+-----------+------+------------+-----------------+
HTMLファイルからデータを読み出す
HTMLデータにtableタグが1つだけあるときは、from_html_one()メソッドを使用します。
code: prettytable_html_one.py
from prettytable import from_html_one
with open('CITY.html') as fp:
data = fp.read()
table = from_html_one(data)
print(table)
HTMLデータに複数のtableタグがあるときは、from_html()メソッドを使用します。
PrettyTableオブジェクトのリストが返されます。
code: prettytable_html.py
from prettytable import from_html_one
with open('CITY2.html') as fp:
data = fp.read()
tables = from_html(data)
for table in tables:
print(table)
参考