Stimulator

機械学習とか好きな技術話とかエンジニア的な話とかを書く

CLI上でtableを綺麗に見たくて各言語のtable表示について調べた

- はじめに -

データ分析、機械学習という仕事柄、csvやtsvを見る機会が多い。

処理する時は大体はpythonのpandasで読み込んで〜とするのだが、コンソール上で作業する時、どうしても「このcsvなんだっけ…」という事が発生する。

cat hoge.csv | head

等として上部だけ見たり、jsonならjqコマンドに流すのだが、いかんせん見栄えの問題で一瞬で判断出来なかったりする。
https://stedolan.github.io/jq/


そこで、table形式にしてコンソール上で表示して見れると嬉しいなと思って調べた事をまとめる記事。
端的に結果を最初に言うと、一般的なコンソールで使うだけならcsvkitなるCLIツールがかなり機能的で便利。tty-tableコマンドとしてjqコマンドのように扱えるtty-tableも綺麗に見れて良い。
CLIツールを今から自前で作るならGoでtablewriterpython上でも資産として利用するならpython-tabulateが便利そうという事が分かった。


追記:

ん〜!わかる!


 

- CLIにtable表示するパッケージのまとめ -

CLIツールとして有名どころではNode.js製のcli-tableがある。
また、cli-tableのAPIと互換性を持ちつつリメイクされたcli-table2や、BoxやProgressBar等の実装も含まれるpixl-cliを使う選択肢がある。

Goだとtablewriter、Pythonだとpython-tabulateが良い。

 

Node.js実装

cli-table

Node.jsで書かれたCLI向けのテーブルビジュアライザ。

github.com

npmが入ってればすぐインストールできる。

npm install cli-table

簡単に扱えて

var Table = require('cli-table');

var table = new Table({head: ['X (train)', 'Y (label)'], colWidths: [20, 20]});
table.push(['hogehoge', 'piyo1'], ['fugafuga', 'piyo2']);
console.log(table.toString());

f:id:vaaaaaanquish:20180503201742p:plain

中身でcolor.jsで色付けしてくれるので見やすい。
Horizontalにするにはlist、Verticalならdictを入れるだけ。
かなり簡易。

 

cli-table2

cli-tableの機能拡張リメイク

github.com

cli-tableのAPIを踏襲している上、セルごとに文字、色、paddingを設定できたり、行列にまたがるセルを生成できるのが強み。

npmで入れる

npm install cli-table2

基本的にはcli-tableと同じ感じで扱える。

var Table = require('cli-table2');
var table = new Table({head:['X', 'Y'], colWidths: [20, 20]});
table.push(
[{colSpan:2,content:'None'}],
['hogehoge','piyo1'],
['fuga', 'piyo2'],
['fugefuga2',{rowSpan:2,content:'piyo4\npiyo5'}],
['fugafuga3']
);
console.log(table.toString());

f:id:vaaaaaanquish:20180503205647p:plain

なんか趣向と外れてきてる気がするが面白い。

以下のAdvanced-usageに面白そうな例が沢山あるので参考に。
cli-table2/advanced-usage.md at master · jamestalmage/cli-table2 · GitHub

 

pixl-cli

上記2つとは少し違って、コマンドラインでNode.jsを作る時のユーティリティが詰まったやつ。
ユーザinputやgraphical info boxes(boxだけでなくtableも扱える)、ProgressBar等が含まれている。

github.com

boxもしくはtableを使うと良さげに表示できる

var cli = require('pixl-cli');
cli.print( cli.box("This is Example!! :D") + '\n');

f:id:vaaaaaanquish:20180503211430p:plain
良さそう。

var cli = require('pixl-cli');
var rows = [
    ['X (data)', 'Y (label)'],
    ['hoge', 'piyo1'],
    ['fuga', 'piyo2']];
cli.print(cli.table(rows)+'\n');

f:id:vaaaaaanquish:20180503211840p:plain

tableも複雑な事はできないが、list投げるだけなので所感は変わらず。

今回は割愛したがProgressBarも便利感あるし、Node.jsでCLIツール作る時はこれ使うと良さそう。

 

Ruby実装

terminal-table

ASCIIでtableをよしなに表示するやつ。

github.com

Rubyなのでgemでインストールする

gem install terminal-table

サンプルを適当に動かす。

require 'terminal-table'
rows = [['hoge', 1], ['piyo', 2], ['fuga', 'test']]
table = Terminal::Table.new :title => "Header Sample", :headings => ['X', 'Y'], :rows => rows
puts table

f:id:vaaaaaanquish:20180503213004p:plain

色も良いけど、やっぱりASCIIが可愛い。
よしなに文字幅等調整するようになってるので、tableのline変えても結構自由に動く。

でも個人的には、RubyCLIツール作る機会がほぼ無くなってしまったので使う機会があれば。

 

tty-table

rubyのTTY toolkit用に作られているtableビジュアライザ。

他のパッケージと違って、インストール時点でコマンドとして使えるのが良さ。
言語関係なくCLIで使うだけなら一番楽だと思う。

また、どの形式でtableを形成するか選べて、unicodeやASCIIが選べる。

www.npmjs.com

gemで入れる

gem install tty-table

TTY::TableやTTY::Table::Rendererが用意されているので、それぞれinitializeして表示。

require 'tty-table'
rows = [['hoge', 1], ['piyo', 2], ['fuga', 'test']]
table = TTY::Table.new rows
renderer = TTY::Table::Renderer::ASCII.new(table)
puts renderer.render

f:id:vaaaaaanquish:20180503214830p:plain

試しにASCIIで出したが良い感じ。

コマンドでも出せて、これが便利感がある。
例えば以下みたくcsvを表示してみる。

cat titanic.csv | head | tty-table

f:id:vaaaaaanquish:20180503215742p:plain
みんな大好きtitanicデータ。

コマンドだと--formatでjsonも指定できたり、--csv-delimiterで'\t'指定すればtsvをtable表示したりもできるので使い勝手がすごい。

 

Go実装

tablewriter

Goだとtablewriter一択だと勝手に思っている。

github.com

知らない間に以下も吸収されていた。
GitHub - crackcomm/go-clitable: Command line (ASCII) and Markdown table for Golang. You probably want to take a look at: https://github.com/olekukonko/tablewriter


機能面では一番使い勝手が良い。
CSVや他Separatorが扱えるだけでなく、行列内のセル、Markdown Formatまで実装されている。
Captionをつける機能もあって、多分CLIでtable作る時は一番便利に扱える。

go get  github.com/olekukonko/tablewriter

以下見たくgoファイル作ってツール化。

package main
import "os"
import "github.com/olekukonko/tablewriter"
func main() {
  data := [][]string{
    []string{"hoge", "String", "SAMPLE"},
    []string{"piyo", "Int", "10"},
    []string{"fuga", "Int", "10"},
  }
  table := tablewriter.NewWriter(os.Stdout)
  table.SetHeader([]string{"X", "TYPE", "VALUE"})
  for _, v := range data {
    table.Append(v)
  }
  table.Render()
}

f:id:vaaaaaanquish:20180503221950p:plain

inputにCSVも使える上、Docも充実。
tablewriter - GoDoc


自前でtable見るツール作るならベストだし、割りとGoでCLIツール作られている事が多くなってきたので絶対使いそう。

 

Python実装

python-prettytable

redhatのdprince氏が作っているprettytable。

github.com

READMEに気合いが入っていている。

pythonなのでpipで導入する。

pip install prettytable

READMEにはset_field_namesなるmethodがあると書いてあったが見当たらず以下のように

from prettytable import PrettyTable
x = PrettyTable()
x.field_names = ['X', 'Y', 'VALUE']
x.add_row(['hoge', 'piyo1', '1'])
x.add_row(['fuga', 'piyo2', '2'])
print(x.get_string())

f:id:vaaaaaanquish:20180503224618p:plain

prettytableの良いところとして、get_html_stringなるmethodがあり、html形式のtable取得ができるので、Webアプリ等に直接返す時にちょっと使えそう。

 

csvkit

CLIツールとして利用するなら最も機能が多い。
コマンドとして入るのですぐ使える。

github.com

pipで導入していく

pip install csvkit

コマンドとして使えるようになってるはず

csvlook titanic.csv

f:id:vaaaaaanquish:20180505103957p:plain

この他、csvgrepやcsvsort、csvjoin、csvstatといったサッとコマンドとして使いたい機能が全てまとまっている。

以下ドキュメントを見るのが最も分かりやすい。
csvkit 1.0.3 — csvkit 1.0.3 documentation

csvlook hoge.csv | head としたり、csvstat見たりすることで、やりたい事は大体実現されている気がする。
良い。

 

python-tabulate

多分多くのPythonパッケージではこれが利用されてると思う。

github.com

pipで導入していく

pip install tabulate

普通にリスト投げるだけで良いので扱いやすい点でユーザが多いのだと思う。

from tabulate import tabulate
table = [["hoge",1],["piyo",2],["fuga",3]]
headers = ["X (data)", "Y (label)"]
print(tabulate(table, headers, tablefmt="grid"))

f:id:vaaaaaanquish:20180503225745p:plain

outputの形式が充実していて、一般的なtableのgrid形式から、PHP MarkdownのpipeやEmacs org-mode、wikiLaTeX markup形式としても出せる。
また、入力としてpandasも対応している。
つよい。


 

でどれが良さそうなのよ

最初にも書いた通り、「すぐコマンドとして使いたい」ならcsvkitがベスト。
tty-tableも良い。cat csvしてtty-tableコマンドに流すだけ。

CLIツールを今から作るならtablewriterでコマンド作って流す形にするのが良さそう。
機能が一番充実しているし、Docも充実している。
Goは良いぞ。

python上でも資産として利用するならpython-tabulateが便利そう。
本当の事を言うと、コンソール上で使いたいというよりxonsh上で使いたいという気持ちが強いので、個人的にはこれを使っていく事になると思う。
python-tabulateにhtml形式のoutput実装してmergeしてもらえば今の所満足そう。

rubyのとnodeは使って見た上で保留。
pixl-cliはめっちゃ使えそうだけどCLIツール最近はGoで書いてて、Node.jsはもっぱらGCP周りで使うくらいなのでう〜ん…

他言語も保留。


 

おわりに

csv簡易table閲覧コマンド作ってxontribにしていくぞ!