もた日記

くだらないことを真面目にやる

CSVの処理で使えそうなコマンドラインツール(column, textql, csvkit, xsv, visidata, csvtotable, daff, tabview)

CSV(またはTSV)を処理するときにはcut, sort, awk, paste, joinといったコマンドを使うことが多いが、CSVの処理で使えそうなコマンドラインツールを簡単に試してみる。
テスト用のCSVデータは下記ページで作成した。
Mockaroo - Random Data Generator and API Mocking Tool | JSON / CSV / SQL / Excel

column以外はGitHubのスター順で紹介している。

column

stackoverflow.com

columnはLinuxコマンドだが検索で結構ひっかかったので紹介。
以下のように見やすいように揃えて出力してくれる。

$ head -n5 test.csv
id,first_name,last_name,email,gender,ip_address
1,Zacharie,Huge,zhuge0@homestead.com,Male,184.185.151.7
2,Simonne,Byllam,sbyllam1@mtv.com,Female,145.149.190.149
3,Richart,Llewellyn,rllewellyn2@netvibes.com,Male,239.93.62.128
4,Esme,Paulitschke,epaulitschke3@who.int,Female,12.66.148.81

$ head -n5 test.csv | column -s, -t
id  first_name  last_name    email                     gender  ip_address
1   Zacharie    Huge         zhuge0@homestead.com      Male    184.185.151.7
2   Simonne     Byllam       sbyllam1@mtv.com          Female  145.149.190.149
3   Richart     Llewellyn    rllewellyn2@netvibes.com  Male    239.93.62.128
4   Esme        Paulitschke  epaulitschke3@who.int     Female  12.66.148.81

lessに渡すときは-#2で左右のスクロール量を指定(数字は自分の好み)、-Nで行番号出力、-Sで折り返さないようにするオプションを使うとよい。

$ cat test.csv | column -s, -t | less -#2 -N -S

空のフィールドを含む場合は、ずれることがあるので以下のように置換するテクニックもある。

$ cat data.csv
1,2,3,4,5
1,,,,5
$ sed 's/,,/, ,/g;s/,,/, ,/g' data.csv | column -s, -t
1  2  3  4  5
1           5

textql

github.com

textqlはCSVデータに対してSQL文が実行できるツール。
go getでインストールできる。

$ go get -u github.com/dinedal/textql...

macOSならbrewでインストールできる。

$ brew install textql

コマンドヘルプ。

$ textql
Usage of textql:

  textql [-console] [-save-to path path] [-output-file path] [-output-dlm delimter] [-output-header] [-pretty] [-quiet] [-header] [-dlm delimter] [-sql sql_statements] [path ...]

  -console
        After all statements are run, open SQLite3 REPL with this data
  -dlm string
        Input delimiter character between fields -dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")
  -header
        Treat input files as having the first row as a header row
  -output-dlm string
        Output delimiter character between fields -output-dlm=tab for tab, -dlm=0x## to specify a character code in hex (default ",")
  -output-file string
        Filename to write output to, if empty no output is written (default "stdout")
  -output-header
        Display column names in output
  -pretty
        Output pretty formatting
  -quiet
        Surpress logging
  -save-to string
        SQLite3 db is left on disk at this file
  -sql string
        SQL Statement(s) to run on the data
  -version
        Print version and exit

以下のようにSQL文を実行できる。-consoleオプションを指定するとREPLが起動するのでSQLiteのように操作できる。

$ textql -header -sql "select count(*) from test" test.csv
1000
$ textql -pretty -header -sql "select * from test where id > 995" test.csv
+------+---------+-----------+-------------------------------+------+-----------------+
|  996 | Louie   | Carlucci  | lcarluccirn@vk.com            | Male | 163.154.17.169  |
|  997 | Robbie  | Speed     | rspeedro@stanford.edu         | Male | 80.50.117.236   |
|  998 | Clemens | Gander    | cganderrp@infoseek.co.jp      | Male | 27.253.50.208   |
|  999 | Joaquin | Blakemore | jblakemorerq@domainmarket.com | Male | 136.100.231.225 |
| 1000 | Dun     | Dilliston | ddillistonrr@amazon.com       | Male | 48.15.139.21    |
+------+---------+-----------+-------------------------------+------+-----------------+
$ textql -console test.csv
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite>

似たようなツールにqもある。

github.com

csvkit

github.com

csvkitはCSV処理関連のツールをまとめたもの。
pipでインストールできる。

$ pip install csvkit

インストールするとin2csv, sql2csv, csvclean, csvcut, csvgrep, csvjoin, csvsort, csvstack, csvformat, csvjson, csvlook, csvpy, csvsql, csvstatコマンドが使えるようになっている。
量が多いので詳細はドキュメントを参照。

$ csvstat test.csv
  1. "id"

        Type of data:          Number
        Contains null values:  False
        Unique values:         1000
        Smallest value:        1
        Largest value:         1,000
        Sum:                   500,500
        Mean:                  500.5
        Median:                500.5
        StDev:                 288.819
        Most common values:    1 (1x)
                               2 (1x)
                               3 (1x)
                               4 (1x)
                               5 (1x)

xsv

github.com

xsvはRustで書かれたコマンドラインツール。
インストールはReleases · BurntSushi/xsv · GitHubからファイルをダウンロードするか、macOSならbrewでインストール。

$ brew install xsv

コマンドヘルプ。

$ xsv help

Usage:
    xsv <command> [<args>...]
    xsv [options]

Options:
    --list        List all commands available.
    -h, --help    Display this message
    <command> -h  Display the command help message
    --version     Print version info and exit

Commands:
    cat         Concatenate by row or column
    count       Count records
    fixlengths  Makes all records have same length
    flatten     Show one field per line
    fmt         Format CSV output (change field delimiter)
    frequency   Show frequency tables
    headers     Show header names
    help        Show this usage message.
    index       Create CSV index for faster access
    input       Read CSV data with special quoting rules
    join        Join CSV files
    sample      Randomly sample CSV data
    search      Search CSV data with regexes
    select      Select columns from CSV
    slice       Slice records from CSV
    sort        Sort CSV data
    split       Split CSV data into many files
    stats       Compute basic statistics
    table       Align CSV data into columns

ヘルプで表示されるサブコマンドのような操作が可能。

$ xsv headers test.csv
1   id
2   first_name
3   last_name
4   email
5   gender
6   ip_address
$ xsv stats test.csv | xsv table
field       type     sum     min                 max                 min_length  max_length  mean   stddev
id          Integer  500500  1                   1000                1           4           500.5  288.6749902572095
first_name  Unicode          Aarika              Zorina              2           14
last_name   Unicode          Abley               von Nassau          3           16
email       Unicode          aalred9h@alexa.com  zswanson5g@tiny.cc  14          35
gender      Unicode          Female              Male                4           6
ip_address  Unicode          0.192.120.163       99.78.161.159       9           15

visidata

github.com

visidataは表形式データのコマンドラインビューア。
pipでインストールできる。

$ pip install visidata

コマンドヘルプ。

$ vd --help
usage: vd [-h] [-f FILETYPE] [-y] [-p PLAY] [-b] [-o OUTPUT] [-w REPLAY_WAIT]
          [-d DELIMITER] [--diff DIFF] [-v] [--encoding ENCODING]
          [--encoding-errors ENCODING_ERRORS] [--regex-flags REGEX_FLAGS]
          [--default-width DEFAULT_WIDTH] [--wrap WRAP]
          [--cmd-after-edit CMD_AFTER_EDIT] [--cmdlog-longname]
          [--col-cache-size COL_CACHE_SIZE] [--none-is-null NONE_IS_NULL]
          [--empty-is-null] [--false-is-null] [--zero-is-null]
          [--error-is-null] [--force-valid-colnames] [--debug]
          [--curses-timeout CURSES_TIMEOUT] [--force-256-colors]
          [--use-default-colors] [--note-pending NOTE_PENDING]
          [--note-format-exc NOTE_FORMAT_EXC]
          [--note-getter-exc NOTE_GETTER_EXC] [--scroll-incr SCROLL_INCR]
          [--skip SKIP] [--profile PROFILE] [--min-memory-mb MIN_MEMORY_MB]
          [--confirm-overwrite CONFIRM_OVERWRITE] [--header HEADER]
          [--delimiter DELIMITER] [--filetype FILETYPE]
          [--save-filetype SAVE_FILETYPE] [--tsv-safe-char TSV_SAFE_CHAR]
          [--clipboard-copy-cmd CLIPBOARD_COPY_CMD] [--pyobj-show-hidden]
          [--pyobj-show-methods] [--replay-wait REPLAY_WAIT]
          [--replay-movement] [--visidata-dir VISIDATA_DIR]
          [--rowkey-prefix ROWKEY_PREFIX] [--cmdlog-histfile CMDLOG_HISTFILE]
          [--regex-maxsplit REGEX_MAXSPLIT]
          [--show-graph-labels SHOW_GRAPH_LABELS] [--plot-colors PLOT_COLORS]
          [--zoom-incr ZOOM_INCR] [--motd-url MOTD_URL]
          [--csv-dialect CSV_DIALECT] [--csv-delimiter CSV_DELIMITER]
          [--csv-quotechar CSV_QUOTECHAR]
          [--csv-skipinitialspace CSV_SKIPINITIALSPACE]
          [--csv-escapechar CSV_ESCAPECHAR] [--fixed-rows FIXED_ROWS]
          [inputs [inputs ...]]

vd test.csvのように実行する。F1でヘルプが表示でき、検索、ソート、編集といった操作ができる。

f:id:wonder-wall:20180725205322p:plain

csvtotable

github.com

csvtotableはCSVをHTMLテーブルに変換するツール。
デモページで確認できるようにソート、検索などが可能。
pipでインストールできる。

$ pip install csvtable

コマンドヘルプ。

csvtotable --help
Usage: csvtotable [OPTIONS] INPUT_FILE [OUTPUT_FILE]

  CSVtoTable commandline utility.

Options:
  -c, --caption TEXT              Table caption
  -d, --delimiter TEXT            CSV delimiter
  -q, --quotechar TEXT            String used to quote fields containing
                                  special characters
  -dl, --display-length INTEGER   Number of rows to show by default. Defaults
                                  to -1 (show all rows)
  -o, --overwrite                 Overwrite the output file if exisits.
  -s, --serve                     Open output html in browser instead of
                                  writing to file.
  -h, --height TEXT               Table height in px or in %.
  -p, --pagination                Enable/disable table pagination.
  -vs, --virtual-scroll INTEGER   Number of rows after which virtual scroll is
                                  enabled.Set it to -1 to disable and 0 to
                                  always enable.
  -nh, --no-header                Disable displaying first row as headers.
  -e, --export                    Enable filtered rows export options.
  -eo, --export-options [copy|csv|json|print]
                                  Enable specific export options. By default
                                  shows all. For multiple options use -eo flag
                                  multiple times. For ex. -eo json -eo csv
  --help                          Show this message and exit.

以下のように変換する。

$ csvtotable test.csv test.html
File converted successfully: test.html

f:id:wonder-wall:20180725205650p:plain

daff

github.com

daffは表形式データを比較できるツール。
pip, npm, gemでインストールできる

$ pip install daff
$ npm install -g daff
$ gem install daff 

コマンドヘルプ。

$ daff --help
daff can produce and apply tabular diffs.
Call as:
  daff [--color] [--no-color] [--output OUTPUT.csv] a.csv b.csv
  daff [--output OUTPUT.html] a.csv b.csv
  daff [--output OUTPUT.csv] parent.csv a.csv b.csv
  daff [--output OUTPUT.ndjson] a.ndjson b.ndjson
  daff [--www] a.csv b.csv
  daff patch [--inplace] [--output OUTPUT.csv] a.csv patch.csv
  daff merge [--inplace] [--output OUTPUT.csv] parent.csv a.csv b.csv
  daff trim [--output OUTPUT.csv] source.csv
  daff render [--output OUTPUT.html] diff.csv
  daff copy in.csv out.tsv
  daff in.csv
  daff git
  daff version

図のようにどこに変更があったのかがわかりやすい。

f:id:wonder-wall:20180725200914p:plain

tabview

github.com

tabviewはコマンドラインのCSVビューアでpipでインストールできる。

$ pip install tabview

コマンドヘルプ。

$  tabview --help
usage: tabview [-h] [--encoding ENCODING] [--delimiter DELIMITER]
               [--quoting {QUOTE_ALL,QUOTE_MINIMAL,QUOTE_NONE,QUOTE_NONNUMERIC}]
               [--start_pos START_POS] [--width WIDTH] [--double_width]
               [--quote-char QUOTE_CHAR]
               filename

View a tab-delimited file in a spreadsheet-like display. Press F1 or '?' while
running for a list of available keybindings.

positional arguments:
  filename              File to read. Use '-' to read from the standard input
                        instead.

optional arguments:
  -h, --help            show this help message and exit
  --encoding ENCODING, -e ENCODING
                        Encoding, if required. If the file is UTF-8,
                        Latin-1(iso8859-1) or a few other common encodings, it
                        should be detected automatically. If not, you can pass
                        'CP720', or 'iso8859-2', for example.
  --delimiter DELIMITER, -d DELIMITER
                        CSV delimiter. Not typically necessary since automatic
                        delimiter sniffing is used.
  --quoting {QUOTE_ALL,QUOTE_MINIMAL,QUOTE_NONE,QUOTE_NONNUMERIC}
                        CSV quoting style. Not typically required.
  --start_pos START_POS, -s START_POS
                        Initial cursor display position. Single number for
                        just y (row) position, or two comma-separated numbers
                        (--start_pos 2,3) for both. Alternatively, you can
                        pass the numbers in the more classic +y:[x] format
                        without the --start_pos label. Like 'tabview <fn>
                        +5:10'
  --width WIDTH, -w WIDTH
                        Specify column width. 'max' or 'mode' (default) for
                        variable widths, or an integer value for fixed column
                        width.
  --double_width        Force full handling of double-width characters for
                        large files (with a performance penalty)
  --quote-char QUOTE_CHAR, -q QUOTE_CHAR
                        Quote character. Not typically necessary.

tabview test.csvのように実行すればよい。?でキーバインドを表示でき、検索やソートなどが可能。

f:id:wonder-wall:20180725201850p:plain

wonderwall.hatenablog.com