標準入力をいい感じにヒストグラムにするCLIツールを作りました。
インストール
Releases · genya0407/hist · GitHub からお好きなバイナリをダウンロードして、適当なパスに展開してください
使い方
なんかこういう感じのテキストファイルがあるとする。
$ cat example.txt 4.486107060301375 4.400612185880518 3.1836054290123 1.8814038706949097 3.367418962291763 2.5550752855238943 2.7646969681590603 4.099374705165457 4.765991107086257 3.1929965581891215 ...(略)
これをhistコマンドの標準入力に食わせると、以下のようなAAが出力される。
cat example.txt | hist 466.1| 468.3| 470.5| 472.7| 474.9|** 477.1|** 479.3|**** 481.4|******** 483.6|************* 485.8|************************ 488.0|****************************** 490.2|****************************************** 492.4|***************************************************** 494.6|******************************************************************* 496.8|********************************************************************** 499.0|******************************************************************************** 501.1|*************************************************************************** 503.3|************************************************************************* 505.5|***************************************************************** 507.7|******************************************************* 509.9|************************************** 512.1|*********************************** 514.3|******************* 516.5|*************** 518.6|********* 520.8|***** 523.0|** 525.2|* 527.4| 529.6| 531.8| +--------------------------------------------------------------------------------+ 995 times +----------------------------------------+ 497 times
縦軸が「値」で、横軸が「頻度」です。上の例だと、500ぐらいの値が出る頻度が一番高くて、その頻度は1000回ぐらいであることがわかります。
ちなみに、横軸の高さを調整するオプションや、値をグルーピングする単位(いわゆる bin)を調整するオプションもあります。
contributionは大歓迎です。あと、入力の行数が少ないときにバグっぽい挙動をするので注意してください。
モチベーション
アクセスログとかDBの中身をヒストグラムにしたいことは稀によくある。例えば「ユーザーあたりのブログポスト数ってどういう分布になってるのかな?」みたいなのを知りたいなど。
継続的に見ていきたいメトリクスならGrafanaとかのキチンとしたツールで見たほうが良いと思うんですが、今この瞬間サッと見れるだけでいいんだけど、というニーズも少なからずあります。そういうときにいちいちjupyter notebookを立ち上げて、seabornの書き方を調べながら、フォント環境が壊れててイライラしたり、gnuplotでいい感じにヒストグラムを書こうとして四苦八苦するのは不毛です*1。
見たい対象のデータがどこにあるのかによっても違ってきますけど*2、アクセスログをテキストファイル形式で扱う場合や、MySQLにクエリを打ってデータ取ってくるときは、シェルからデータが生まれてくるわけで、シェルのなかでグラフ描画までできたら楽でいいですよね。
というわけで、「シェルから生まれてきた数字列をそれっぽいヒストグラムAAに起こす」という処理を例によってRubyワンライナーで毎度毎度書いてたんですが、ちゃんとしたヒストグラムを書くのは意外にめんどくさいのでCLIツールにしちゃおと思ったのが、今回histコマンドを作ろうと思ったきっかけです。
メイキング
Rustの良いところ
CLIツールがいい感じに作れてすごかった(小並感)。
この argopt ってcrateがめっちゃ便利。
詳しくは上のリンクを読んでもらったら良いんですけど、例えば以下のように書いてコンパイルして実行すると、
use argopt::cmd; #[cmd] fn main( #[opt(short = "b", long = "bin")] bin: Option<f64>, #[opt(short = "l", long = "bar-length", default_value = "80")] bar_length: i64, ) { // 略 }
以下のような出力が得られます。
$ hist --help hist 0.1.0 USAGE: hist [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information OPTIONS: -l, --bar-length <bar-length> [default: 80] -b, --bin <bin>
もちろんmain関数の引数にはいい感じに引数が渡ってきます。これはちょっと感動的に便利ですよね。 今回RustでCLI作ろうと思ったきっかけの1/4ぐらいは、argoptの紹介記事を読んだことです。
余談ですが、最新のバージョン(v0.1.1)のargoptは、dependencyとしてargoptを指定するだけじゃ動かなくて、structoptも指定してあげないとダメっぽかったので、issueを立てて報告しました(英語が拙い)。
Github Actionsがべんり
これもすごかった。
この記事を真似するだけで、
という魔法みたいな状態を構築することができます。当然ビルドされたバイナリは展開してPATHに置くだけで実行できる。シングルバイナリ最高です。今まで僕がRubyでCLI作って配布方法をウンウン悩んでたのは何だったんだろう...
まとめ
標準入力からヒストグラムを描画するCLIツールをRustで作りました。RustはCLIツールを作成・配布する上でとても楽な選択肢であり、オススメです。