Perl Hackers Hub

第69回 表形式データを操るUNIXシェル型Perl製コマンド群 ―ビッグデータ時代の汎用的なデータ整備と分析のために(2)

この記事を読むのに必要な時間:およそ 1 分

前回の(1)こちらから。

表データの把握

(2)では,表データの把握に役立つコマンドを紹介します。紹介するcolsummaryの結果を眺めることで,入力データ各列の値の範囲や最頻値などを容易に把握できます(a)⁠b)⁠d)⁠f)は部分的に,(g)⁠h)⁠i)⁠j)は大幅に解決します⁠⁠。vennにより,複数のデータの重なり具合を把握できます(e)を検出し,(i)⁠j)を解決します⁠⁠。適当な列をcselでいくつか選んで,crosstableでクロス集計表を作成することで,2列の値の関係がわかります(c)⁠d)を簡便に検出できます⁠⁠。

クロス集計表の作成 ─⁠─crosstable

crosstableの基本機能は,クロス集計表を出力することです。Excelのピボットテーブルとほぼ同じですが,Excelだとマウス操作を伴うので再現性に難があります。シェル芸やSQLでは実現困難です。

Twitterから収集したデータに対する例

Twitterのツイートを特定のキーワード群で検索して取得したデータであるtwitter.tsvに対してcrosstableを実行し,何日の何時台に何件取得したかを調べてみましょう。

twitter.tsvは各行に日付,時刻,ツイート内容が記録されているので,時刻の時未満の部分を除去し,crosstableで集計します。

各行「年-月-日\t時:分:秒\t発言内容」の:以下をPerlで除去
$ crosstable <( perl -pe's/:.*//' twitter.tsv )

得られた結果をターミナルからExcelにコピー&ペーストし,Excelの条件付き書式の機能で値に応じて色を付けたのが図1です。

図1 crosstableでツイート収集件数を日付×時刻帯ごとに集計

図1 crosstableでツイート収集件数を日付×時刻帯ごとに集計

出力からの知見

図1から,Twitterのツイートの取得に失敗していた日時や,投稿が不自然に増減した日時を色の濃さで容易に判読できます。また,2列に現れた値の範囲や欠損を明確にする目的にも使えます。

全列の特徴量の表示 ─⁠─colsummary

全列のさまざまな特徴量を,読みやすく整理して画面に表示するのがcolsummaryです。列の特徴量として表1の各項目を色付きで出力します。

表1 colsummaryの出力表の各列の意味

出力表の列名
(列の色)
意味
列番(白)入力表の列の番号。1始まり
異なる値(緑)入力表のその列が,何通りの異なる値を持っていたかを表す。すべて同じ値なら1となる
値の範囲(白)各出現値を「0の0回以上の繰り返し」「数値」「それ以外の文字列」に分類し,それぞれを最小値~最大値の形(または辞書順の先頭~末尾)で表し,|で区切る
最頻値(白)頻度(出現回数)の多い値を,上位から順に抽出指定数で指定した個数だけ|で区切って出力する
頻度(重複)
(緑)
上位と下位の頻度を,それぞれ抽出指定数で指定した個数だけ|で区切って出力し,上位~下位の形で表す。同じ頻度が複数ある場合は,括弧内にその重複数を示す
桁数(藍)各値の文字数を0か1以上により|で区切り,1以上を最小値~最大値の形で表す

これらの出力項目を目で読み取ることで,多数の表が提供された場合でも全列の意味がわかりやすくなります。その結果,どの表のどの列が大事なのか,複数の表のどの列を組み合わせると意味のある結合になるのかなどが一目瞭然となり,分析がはかどります。

TRC書誌情報の表に対する例

次の例では,図書館流通センターのTRC新刊図書オープンデータのページの「TRC新刊書誌情報 2021年06月05日(tsv形式⁠⁠」に対して,colsummaryを実行しています。

ダウンロードしたZIPファイルの解凍。次で使うT*0710.txtを生成
$ unzip TRCOpenBibData_20210710.zip

出力表の視認性のためにexpandtabを使用
$ colsummary -g3 -v9 -j -m0 T*0710.txt | expandtab -s30

実行結果は図2です。図2の出力の18行は,T*0710.txt注1にあった18列に対応しています。4個のオプションの指定注2は図を見やすくするためであり,なくともかまいません。

図2 colsummaryでTSVファイルの各列の性質を把握

図2 colsummaryでTSVファイルの各列の性質を把握

注1)
T*0710.txtは,ここではTRCOpenBibData_20210710.txtを意味し,読みやすさのためにワイルドカード*を使いました。ほかのファイルが該当しなければ,キーの押下回数を減らすことにも有用です。
注2)
-g3は,表1の抽出指定数の指定です。-v9は,出現値の9文字目より先を非表示にします。-jは,出力の日本語化です。-m0は,⁠数値データに有用な)各列の数値平均出力の抑制の指定です。

複数データの重なり把握 ─⁠─venn

vennは,各ファイルで延べ何個の文字列が行として出現したかを,具体的な出現値(辞書順の先頭と末尾)と併せて出力します。コマンド名のもととなったベン図は,集合どうしの重なりを表す図です。vennでは出現延べ数と具体値も出力されるため,ベン図だけではわからない多くの情報を整理して読み取ることができます。これにより,複数のファイル上のデータの重なり具合や包含関係を把握できます。

4個のファイルに対する例

ここでは,ファイルを4個用意する代わりに,プロセス置換を4個同時に使って実演します。

自作シェル関数yを作成。引数を文字ごとにばらして改行を挿入
$ function y(){ echo -n $* | perl -pe's/./$&\n/g' }

cardi.はcardinalityの略。minstrとmaxstrは辞書順の先頭と末尾
$ venn <(y ABCCC) <(y AABDEFG) <(y ABBDEFG) <(y DEEEFG)
cardi.  file1   file2   file3   file4   minstr  maxstr
2.      2       3       3       0       'A'     'B'
1.      3       0       0       0       'C'
4.      0       4       4       6       'D'     'G'

最初に自作シェル関数yを定義します。yは,引数を1文字ずつにばらして改行を挿入します。

次のコマンドラインは,あたかも{A,B,C,C,C}{A,A,B,D,E,F,G}{A,B,B,D,E,F,G}{D,E,E,E,F,G}に対応する4個のファイル(以下,file1~4とします)があって,それぞれの各行に1文字を格納した状態で注3⁠,その4ファイルをvennに与えるかのように振る舞います。

vennのアルゴリズム

上記の例をもとに,vennのアルゴリズムを説明します。

まず,A~Gの各文字列が,file1~4に「現れたか/否か」「1/0」で表現します。すると,A~Bは1110,Cは1000,D~Gは0111となり,出力にある3パターンに分類されます。

次に,各パターンの異なる文字列を数えると,それぞれ2個(A,B⁠⁠,1個(C⁠⁠,4個(D,E,F,G)です。それを,左端のcardi.列注4に記載します。

file1~4のそれぞれに,A~Bは2,3,3,0回,Cは3,0,0,0回,D~Gは0,4,4,6回現れています。これらの数を出力の各ファイルの列に記載します。

最後に,各パターンに出現した文字列の辞書順の先頭と末尾を右端のminstrとmaxstrの列に記載します。

出力表から読みとれること

出力の0の出現パターンなどから,⁠file1の持つ2+3+0=5個の文字列と,file4の持つ0+0+6=6個の文字列は共通部分がない⁠⁠,文字列Cは「出現延べ回数は3+0+0+0=3である」⁠file1以外に現れない」⁠同じ出現パターンを示す文字列はほかにない」⁠DやGと同じファイルに出現することはない」ことが読み取れます。

注3)
実務では,vennが読み取るデータは1文字ずつではなくて,あるサービスを各月で利用した会員の会員番号7文字だったりします。
注4)
cardi.はcardinalityの略で,異なる要素の数を意味します。⁠男性」⁠女性」の値のみ存在する場合,これらの値がそれぞれ1個あっても多数あってもcardinalityは2です。

著者プロフィール

下野寿之(しものとしゆき)

普段はデータ分析のお仕事。最近は新型コロナ関係が多め。自由度2のt分布や楕円球を使った数理モデルで数値の意味を近年考えている。16年前に量子計算で博士を取得し,7年前に医学統計学を学ぶ。

GitHub:tulamili
SlideShare:https://www.slideshare.net/shimonotoshiyuki