【Tableau】開始日基準で指数化して表示する

Tableau で時系列データを開始日基準で指数化（開始日の値が 1 になるようにスケーリング）するよい方法がわからなかったので以下のようにやりましたが、別のよりよい方法をお教えいただけますと幸いです。<font color="deeppink">→ ［2022/11/16 追記］ @LowSE01 さんが詳細に教えてくださったので記事を修正させていただきました。ありがとうございます。</font>
### 前提
「年月日」（日付型の不連続ディメンション）と「価格」（小数型の連続メジャー）が認識されているものとします。以下のような tsv ファイルを読み込むとたぶん自動的にそうなると思います。
```
年月日,価格
2021/9/1,120.7
2021/9/2,119.1
2021/9/3,120.3
...
```

### 適切な方法

「計算フィールドの作成」から適当な名前（「指数化価格」など）で以下の計算フィールドを作成するだけです。
```SUM([価格]) / LOOKUP(SUM([価格]), FIRST())```

後はこれを適当に描画してください（適切ではない方法の 3. を参考）。

### 適切ではない方法

今回のケースでは以下の手順でも同じグラフが描けますが、手間がかかるだけでなく、Tableau に余計な負荷もかけるので適切な方法ではありません。ただし、この方法では指数化の基準日を表示範囲外の日付に取ることができます。

1. 「パラメータの作成」から以下のパラメータを作成する。
    - 「開始日」： データ型を「日付」にして適当な開始日を入れる。
    - 「終了日」： データ型を「日付」にして適当な終了日を入れる。
1. 「計算フィールドの作成」から以下の計算フィールドを作成する。
    - 「年月日表示用フィルタ」： ```[年月日] >= [開始日] AND [年月日] <= [終了日]```
    - 「基準日フラグ」： ```IIF([年月日]=[開始日], 1.0, 0.0)```
    - 「指数化価格」： ```[価格] / {FIXED: SUM([価格] * [基準日フラグ])}```
1. 「年月日」を「列」にドラッグし、「指数化価格」を行にドラッグして折れ線グラフを表示する。
    - デフォルトで「年月日」をドラッグしたとき「年(年月日)」となってしまう気がするので、ドラッグしてからプルダウンで「日（2つ表示されているが下の方が連続値なのでそちらを選ぶ）」を選び日次グラフにする。
1. 「年月日表示用フィルタ」を「フィルター」までドラッグし、「真」をチェックする（ことで「開始日」～「終了日」のみが表示されるようにする）。
1. 「開始日」「終了日」をそれぞれ右クリックして「パラメータの表示をチェックしておく（ことで閲覧者が開始日と終了日を変更できるようにする）。

### 解説

※ 自分の理解用です。何かありましたらご指摘ください。

今回のデータはディメンションが「年月日」のみなのでわかりづらいですが、「年月日」を「列」に、「価格」を行にしてグラフを描画するとき、Tableau は「年月日」ごとの「価格」の合計を描画しています。

|[年月日]|SUM([価格])|
|:--|--:|
|2021/09/01|120.7|
|2021/09/02|119.1|
|2021/09/03|120.3|

今回ほしい「指数化価格」は以下になりますが、2021/09/02 の行に 120.7 という値はないので、いまあるカラムに基本的な式を適用してもこの列はつくれません。

|[年月日]|SUM([価格])| [指数化価格] |
|:--|--:|--:|
|2021/09/01|120.7|120.7 / 120.7|
|2021/09/02|119.1|119.1 / 120.7|
|2021/09/03|120.3|120.3 / 120.7|

そこで、表計算関数の `LOOKUP` を用いると、ある列の値をオフセット行だけずらした値を覗くことができます。なので、最初の行までのオフセットを指定すれば最初の行が覗けます。便利なことに、最初の行までのオフセットをとる `FIRST()` という関数が用意されています。

|[年月日]|SUM([価格])| LOOKUP(SUM([価格]), FIRST()) | [指数化価格] |
|:--|--:|--:|--:|
|2021/09/01|120.7|120.7|120.7 / 120.7|
|2021/09/02|119.1|120.7|119.1 / 120.7|
|2021/09/03|120.3|120.7|120.3 / 120.7|

ここまでくれば目的の指数化価格は割り算で手に入ることがわかります。

◆

では、適切ではない方法の方は何が適切でなかったのかというと、まずこちらの方法では非集計な「基準日フラグ」というフィールドを用意しました。

|[年月日]|[基準日フラグ]|[価格]|[価格] * [基準日フラグ]|
|:--|--:|--:|--:|
|2021/09/01|1|120.7|120.7|
|2021/09/02|0|119.1|0|
|2021/09/03|0|120.3|0|

こうしておいて、LOD 計算の `FIXED` を用いて `{FIXED: SUM([価格] * [基準日フラグ])}` とすると、「年月日ごとという垣根は無視してデータ全体での [価格] * [基準日フラグ] の和を計算せよ」となり、120.7 という値が手に入ります。それを用いて以下のように「年月日」ごとの集計をしていました。

|[年月日]|SUM([価格] / 120.7) |
|:--|--:|
|2021/09/01|SUM(120.7 / 120.7)|
|2021/09/02|SUM(119.1 / 120.7)|
|2021/09/03|SUM(120.3 / 120.7)|

こちらの方法では 120.7 を得る方法に無駄があります。また、「年月日ごとという垣根は無視してデータ全体での～」という計算はディメンションに対するフィルターより前に処理されるので、例えば表示範囲は1週間だけであったとしても、データ全体が3年分あったら、この計算は3年にわたるデータ全体に対してなされることになります。

しかし、ディメンションに対するフィルターより前に処理されることを逆手に取ると、指数化の基準日を表示範囲外に取ることができます（例えば、表示範囲は 9/3 からだが基準日は 9/1 というように）。「適切ではない例」で「開始日」とは別に「基準日」パラメータを作成し、「基準日フラグ」を基準日をもとに作成するとこれが実現できるのがわかると思います（ただこの目的のときでも式に改善点があると思います）。

### 参考文献
- [Tableau での計算の種類](https://help.tableau.com/current/pro/desktop/ja-jp/calculations_calculatedfields_understand_types.htm)
    - 基本的な式、LOD 計算、表計算があります。
- [Tableau の操作の順序](https://help.tableau.com/current/pro/desktop/ja-jp/order_of_operations.htm)
    - LOD 計算の FIXED はディメンションに対するフィルターより前に処理されます。
- [適切な計算の種類の選択](https://help.tableau.com/current/pro/desktop/ja-jp/calculations_calculatedfields_understand_which.htm)
    - 視覚化の粒度と一致しているならば LOD 計算ではなく表計算を用いよとあります。