ガースー日記

笑ってはいけないネタに惹かれて、昔は黒光り日記、というブログ名でやってました。(大学生のノリでした..)

Tableauにおけるデータが存在しないこととNULLは異なる

Tablaeu DataSaberチャレンジ中

年始に建てた月1でブログを書く、ということが順調に達成できず既に4月も中旬です。笑

 

2022年2月から、Tablaeu Data Saberという資格を取るべく挑戦を進めています。

DataSaberとは何ぞや、という紹介をすると長くなってしまうので、詳しくは下記リンク等を参照ください。

datasaber.world

 

資格と言っていますが、Tableau社が認めた公式の資格ではないです。

ですが、日本ではすでに700名以上のDataSaberがおり(2022年4月現在)、日々データドリブンな世界に向けて活動を進めています。

 

DataSaberに挑戦する過程で、課題を通してダッシュボードを作成したり、久しぶりにBIツールに向き合う日々が続いています。

その過程で、自分の理解が甘いけれどももうちょっと詳しく知りたい、という内容をブログにまとめることにしました。

 

課題感

表計算の挙動が良く分かっていない。

 

私自身はデータエンジニアとして活動をさせてもらっているため、SQLを書いたり、そもそも分析しにくいデータがあったら作ってしまえ、と思ってしまう派です。

 

また表計算に対するイメージとして、自分が必要としてるデータ構造になっていないから、それを補完するときに機能する、と考えていました。

アナリストが求めているデータを作る時間や工数が足りないときに、それが表計算で解消できるのであれば知っておいて損は無いです。

 

あり得るのか分かりませんが、表計算でカバーできる範囲を知っていることで細かくデータを作りすぎないことに役立つかも、という期待もあります。

 

では実際に、こういうことできないんだっけ?と感じたダッシュボードを出してみます。

https://public.tableau.com/app/profile/suga.toshifumi/viz/0_16496890547280/sheet8

 

f:id:drizzlyrain:20220413221612p:plain

 

Tableauのサンプルスーパーストアから期間を絞ったデータを利用しています。

折れ線グラフに対して、平均線が引かれています。

パッと見るとだまされてしまうのですが、4月14日週の売上は存在しないデータになっています。

 

やりたいこと

4月7日週・14日週・21日週の平均売上を集計したい。

 

4月7日週:27,206円

4月14日週:売上が発生していないため、データが欠損扱いになる

4月21日週:86,603円

という売上データが入ってるため、単純に平均すると(27206 + 86603)/2 = 56905円になってしまいます。

 

欠損値のデータを0埋めして、(27206 + 0 + 86603)/3 = 37936円をアウトプットにしたい、というのがゴールです。

 

結論

残念ながら、今回の事例は表計算で解消できないパターンでした。

 

調査・検証内容

そもそも論、表計算、という名前の通りクロス集計表に落とし込める必要があります。

最初に折れ線グラフで可視化しているのは、集計の集計を行うにあたってTableauの平均線、という機能が便利だったためです。

 

Tableauは問い合わせ内容が充実しているので、調べると結構出てきます。

今回であれば、以下のケースが近しいそうと思い試していきました。

kb.tableau.com

 

まず、1と2番の例を一緒に試してみました。

ZNのみを利用すると、値が入りません。

f:id:drizzlyrain:20220413223119p:plain

 

PREVIOUS_VALUEとIFNULLを利用すると、2012年の最初のデータはZNの方も0が入るようになりました。

ただ、2013年4月14日週のデータは、IFNULLは前の週の値が入り、ZNの方は0が入っています。

f:id:drizzlyrain:20220413223133p:plain

 

PREVIOUS_VALUEに関しては単語の通りなので、分かりやすかもしれません。

前の行のこの計算の値を返します。
現在の行がパーティション内の最初の行の場合は指定された式を返します。

blog.truestar.co.jp

 

今回は以下のような計算式を利用しているので、2012年の売上は先頭だったので0が入った。

2013年4月14日週は、直前の週の売上が入った、という感じです。

IFNULL(
  AVG(売上),
  PREVIOUS_VALUE(0)
)

 

ZNに関して

式が NULL でない場合は式を返し、それ以外は 0 を返します。

NULL 値の代わりにゼロ値を使用するには、この関数を使用してください。

help.tableau.com

 

なんかこの単語だけ見ると、エンジニアとかSQLに慣れてる人の方が引っかかりそうな気がしますね。笑

要は4月14日週の売上はNULLじゃないのか?という話です。

 

Tableauにおいて、データが存在しないこととNULLは異なります。

 

なのでZN関数のみを利用しても有効に働きませんでした。

PREVIOUS_VALUEを利用することで、データ枠が生まれました。

それによって、平均売上がNULLとして表現されたわけです。

 

結果、ZNを利用することで0埋めされた、という感じですね。

 

NULLが無いなら、作ってあげれば良いじゃない

という発想を抱いて、データブレンドを無理やりすれば行けるんじゃね?と思ったのが、きっかけです。

 

完全にアンチパターンですが、同じデータソースを読み込ませ日付週はプライマリーから、売上データはセカンダリーデータソースから計算してみました。

 

結果は、下記のように惨敗です。

f:id:drizzlyrain:20220413230302p:plain

 

一応TableauにもSQLと同じで処理順序があります。

ブレンドで行けるのでは?と思ったのも、結合が先に起きてAVGの集計が行われるためです。

help.tableau.com

 

同じデータソースを複製し、データブレンドしてもデータ枠が存在しないところはNULL値ではなく、データ枠が欠落されたままになります。

 

ちょっとここは自分の中でも腹落ちができていないのですが..

実はこの部分、Tableauのテクニカルサポートの方に質問しつつ、理解を深めていました。

サポートいただいた方には、この場も借りてお礼をさせていただきます。

 

恐らくFROM句側にデータが無いので、JOINさせてもデータが無いよ、ということだとは思います。

家電カテゴリの中では、2013年4月14日週の売上は発生していないので、日付データも存在してない、という理解です。

(であれば、カレンダーとなるテーブルが別にあれば、ブレンドで行けるのでは?と思ったりしてますが、検証できていないです)

 

最終的には、私がやりたかったケースは元データ自体を編集しないと解消できない、という返答をいただいてしまいました。

 

ただ、データが存在しない= NULLという発想になりがちな中で、両者の違いを感じられたことは良い経験になりました。