Alteryxとtidy data #alteryx_ug

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、小澤です。

当エントリは『Alteryx User Group in 東京 Advent Calendar 2018』14日目のエントリです。

昨日13日目の記事はniinoによる『Alteryxをもっと活用したい!「データ解析の実務プロセス入門」を読む』でした。

データが綺麗な状態とは?

先日Alteryxユーザ会にて、ワークフロー作成のお題を作成しました。

ここでのお題は、見た目だけを整えてコンピュータを使った分析ではそのままでは全く使えないデータをキレイにするというのがメインテーマでした。 みなさん、大変苦労していたようでお題作成者冥利に尽きるというものです。

さて、「データは分析で使いやすいようにキレイにするべき」とよく言われますが、どういう状態のデータがキレイなデータと呼べるのか?考えたことはありますでしょうか? Alteryxの利用有無にかかわらず普段からデータ分析をされる方にとっては「何をいまさら」と思われる方は多いかもしれませんが、実際どういう状態のデータが欲しいか?と言われると、なかなか明確に定義するのは難しいのではないでしょうか? とりあえず最低限テーブル形式になっててほしいなどあるかもしれませんが、それでもつらいときはつらいですね。

今回は、そんなキレイなデータの定義の一つとしてtidy dataというものを見ていきたいと思います。

tidy dataとは

tidy dataとは日本語では整然データと呼ばれる構造のデータ形式になります。

統計解析言語であるR言語界において、神ともいわれるHadley Wickham氏によって提唱されたものになります。

元の論文は以下から読むことが可能です。

こちらは、Colorless Green Ideasというサイトで日本語訳も公開されています。

論文の中でtidy dataとは以下の3つを満たすものであると定義されています。

  1. 個々の変数が1つの列をなす。
  2. 個々の観測が1つの行をなす。
  3. 個々の観測の構成単位の類型が1つの表をなす。

また、この条件を満たさないデータのことをmessy data(雑然データ)と呼んでいます。

今回はこの論文の内容に基づいて、tidy dataと何なのかについてみていき、後半ではAlteryxでの扱いについて解説していきたいと思います。

実際のデータでみてみる

さて、整然データである3つの条件を書きましたが、これだけではよくわかりません。 そこで実際の例を見てみましょう。

データをテーブル形式で記録する際には様々な形式が考えられます。 例えば以下のようなデータを考えます。

treatmaentA treatmentB
John Smith - 2
Jane Doe 16 11
Mary Johnson 3 1

これはtreatmentA, Bであらわされるなんらかの実験を行った結果の観測値のようなものと想定してください。 なお、"John Smith"さんは参照している元の論文によるもので私とは関係ありません。

このデータは行列の転置を行って以下のように表現することも可能です。

John Smith Jane Doe Mary Johnson
treatmantA - 16 11
treatmentB 2 11 1

これらのデータはいずれもtidy dataではありません。 これをtidy dataにすると以下のようになります。

name treatmant result
John Smith A -
John Smith B 2
Jane Doe A 16
Jane Doe B 11
Mary Johnson A 11
Mary Johnson B 1

このデータでは、1つの列が1つの変数となっており、また各行は1つの観測データとなっています。 欠損値に関する扱いもありますが、この状態であれば1行目を外すなど安全に扱うことが可能です。

論文中ではよくあるmessy dataとそれをtidy dataに変換する方法について記載されています。 これらの内容に関しては、実際にAlteryxでどのように扱うかも合わせてみていきましょう。

また、論文の日本語訳を行っているサイト内にて、tidy dataを満たすためのそれぞれの条件とmessy dataの対比で解説しているページがあります。 こちらは、複数地点の天気の観測についてを例に解説しており、非常にわかりやすい内容となっているため、こちらも併せてご参照ください。

Alteryxでデータをtidyに変換する

論文中では5つの例でmessy dataをtidy dataに変換しています。

  • 列見出しが、値であって変数名でない
  • 複数の変数が、1つの列に格納されている
  • 変数が、行と列の両方に格納されている
  • 観測の構成単位の類型が、同じ表に複数格納されている
  • 1つの観測の構成単位が、複数の表に格納されている

これらの変換を実際にAlteryxでやってみましょう。 なお、扱うデータ(と元論文でのRのコード)は著者のGithubから取得可能ですので、ご自由にお試しいただくことが可能です。 (Rのコードも公開されてるので全部Rツールでやってもいいんですよw)

列見出しが、値であって変数名でない

最初の例は「列見出しが、値であって変数名でない」となります。 この例ではデータは以下のように、各階級値ごとに列となっています。

このデータは個々の変数が1つの列をなしてない状態となっています。 これをtidy dataに変換すると以下のようになります。

これを実現するAlteryxのワークフローは非常に簡単です。

Transposeツールで縦持ちへの変換を行ってSelectツールで列名を整えるのみです。 Transposeツールの設定は以下のようになっています。

religionをKey Fieldsに、それ以外をData Fieldsにしています。

別な例として、次のようなデータを見てみましょう。

これはビルボートにおける各楽曲の週ごとのランキングです。 このデータは楽曲に関する情報の部分はいいのですが、週ごとのランキングが列になっています。 これも同様にTransposeツールで変換します。

Selectツールで列名を整えた結果は以下のようになります。

このデータにはまだ、artistやtimeなど繰り返し同じ値が出現する問題が残っています。 この問題は「観測の構成単位の類型が、同じ表に複数格納されている」で扱います。

複数の変数が、1つの列に格納されている

続いては、「複数の変数が、1つの列に格納されている」となります。

以下のようなデータセットがあります。

このデータにおける列名は以下のような規則性になっています。

列名 性別 年代
m014 男性 0-14
m1524 男性 15-24
f014 女性 0-14
f1524 女性 15-24

先頭の文字が性別、その次の数値が年代の階級幅となっているわけです。

これを整形するワークフロー全体像は以下のようになります。

最初のSelectは列名などをちょっといじくる程度のものなので無視して問題ないです。

これはまず先ほどと同様Transposeツールで変換します。

次にこのcolumn列を分解していきます。 これは少々骨が折れる作業ですね。

今回は愚直に以下のルールで取り出しました。

  • 性別は先頭1文字を取り出す
  • 年代は以下のルールに従う
    • 全体で4文字 : 2文字目が開始、最後の2文字が終了
    • 全体で5文字 : 2-3文字目が開始、最後の2文字が終了
    • 全体で3文字 : 最後の2文字が開始
    • 全体で2文字 : 不明

以下のようなFormula式を使っています。

sex列 :

left([column], 1)

age列 :

IF
  length([column]) == 4
THEN
  left(right([column], 1), 2) + "-" + right([column], 2)
ELSEIF
  length([column]) == 5
THEN
  left(right([column], 2), 3) + "-" + right([column], 2)
ELSEIF
  length([column]) == 3
THEN
  right([column], 2) + "-"
ELSE
  "unknown"
ENDIF

Selectツールで列の順序などを調整して以下のような結果になります。

変数が、行と列の両方に格納されている

続いては、本来列にあってほしいものが行の値になってたり、行の値であってほしいものが列に入ってたりするパターンです。

以下のデータでは、年月ごとに1列が1日分の観測データとなっています。 また、element列にTMAX(最高気温)、TMIN(最低気温)という値が入っています。

このデータを1日ごとの観測データに変換します。 結果としては、以下のような形式にします。

このデータでは観測された日ごとのレコードになっており、それぞれ最高気温と最低気温の列を持っています。

この処理を実現するワークフローは以下のようになります。

まず最初にTransposeツールで、日ごとの観測値を縦持ちに変換しています。

これに対して、Formulaツールで年月日を合体させてdate列を作成しています。

[year] + "-" +
PadLeft([month], 2, "0") + "-" +
PadLeft(Replace([Name], "d", ""), 2, "0")

year列はそのまま利用可能です。 month列は2桁にそろえるため、PadLeft関数でゼロ埋めしています。 日付の部分に関しては、Transpose前の列名から「d」を除いてゼロ埋めしたものを使っています。

その後、Selectツールで年月日それぞれの列を除きます。 今回は見通しをよくするため、NA(値なし)の行をのぞいてみました。 これは実際に分析する際には必要に応じて判断してください。 結果は以下のようになります。

最後にCross Tabツールでelement列の値を列方向に変換することで1レコードが1日分の観測データとなりました。

観測の構成単位の類型が、同じ表に複数格納されている

「列見出しが、値であって変数名でない」で登場したビルボードのデータの一部を改めて確認してみます(一部列を省略しています)。

このデータは同じ楽曲を複数の週で観測しているので、artistやtimeなどを含めた項目が何度も出現しています。

これを防ぐにはRDBにおける正規化のように2つのデータに分けます。

この処理を実現するワークフローは以下のようになります。

まず、マスタデータとなるartist, track, timeの列のみをSelectツールで取り出します。 その値をUniqueツールで重複削除したのち、RecordIDツールで一意なIDを振っています。

このデータと元のデータを上記3つの項目でJoinします。

あとはランキング実績のほうに必要な列のみに絞って完成です。 なお、このワークフローではJoinツールの後にSelectツールを配置することでその処理を明示的にしていますが、Joinツール内で同様の処理もまとめて行っても問題ありません。

データ分析を行う際には正規化されたテーブルをそのまま扱えるようなツールはないので、いずれにせよ分析する際には再度ジョインする必要があります。 そのため、この処理には良し悪しありますが、必要に応じて使い分けてください。

1つの類型が複数の表にある

最後は先ほどの「観測の構成単位の類型が、同じ表に複数格納されている」の逆パターンです。

こちらは元論文でもサンプルデータがありませんので、文章のみでの解説となりますが、やることはいたってシンプルで先ほどのデータを再びジョインするようなものだと思ってください。

おわりに

今回は、キレイなデータとはどういったものなのかの定義の1つとしてtidy dataを紹介して、ありがちなパターンでAlteryxを使って変換する方法を解説しました。

世の中のデータのほとんどはtidy dataではありません。 また、tidy dataのみが常に最高のデータ形式であるわけではありません。 場合によってはデータが他の形式になっているほうが都合がいいこともあるでしょう。

また、tidy dataはプログラムから処理しやすい形式であって、人間にとってわかりやすい形式を意識しているわけではありません。 人間にとって見やすい形式とプログラムから操作しやすい形式がイコールではないことは常に意識しておくべきでしょう。

データ分析では、"今やろうとしてること"が分析をするフェーズなのか人に見せるものをつくるフェーズなのか意識して、適切なデータの持ち方を考えることが重要になります。

次回はtruestar小海老澤さんによる「Alteryx Inspire 2018 Toyotaの機械学習事例紹介」の予定です。 次回もお楽しみに!