Power BI におけるデータ変換の心がけ ～ 変換は 可能な限り 上流で ～

# はじめに
**Power BI** に限らず、**BI** ではよく言われることを今回は取り上げてみたいと思います。具体的な **Tips** や何かの使い方ではなく、考え方のお話です。

# まずはこちらの YouTube をご覧ください
この動画は **Power BI** に興味のある方ならご存知だと思いますが、**Guy in a Cube** にて、2022/10/06 に公開された「Where do you add that new column in any analytics tool?」という動画です。
<iframe width="560" height="560" src="https://www.youtube.com/embed/OAlys79j81Q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

# 動画の内容
タイトルを動画の内容に照らし合わせて、意訳すると、

**「列を新しく作るとしたらどこでやるのがいいの？」**

といった感じでしょうか。

動画の中では、「姓と名が元の列に含まれていて、今あなたはフルネームを格納する列を作成したい」という例をもとに話がされています。

- DAX で計算列を作る？
- Power Query で値を結合した列を新たに作る？

最初に思いつくのはこの2つでしょう。

そして BI でよく言われる格言的なものが紹介されています。

:::note info
Data should be transformed as far upstream as possible, and as far downstream as necessary.
:::

日本語にすると

:::note info
データは、可能な限り上流で変換し、必要に応じて下流で変換されるべきだ。
:::

といった感じでしょうか。

今回はこれについて考えてみたいと思います。

# DAX でやる？Power Query でやる？
「姓と名が元の列に含まれていて、今あなたはフルネームを格納する列を作成したい」場合、**DAX** でも **Power Query** でも対応が可能です。
例を挙げて、やってみましょう。以下、今回使用するデータです。

## とりあえず姓と名を別々にExcelでデータを作ってみる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/aa2cf92c-84f7-1c44-2b40-03b68767971d.png)
Excel で簡単なデータを作成しました。Excel でテーブルを作成した場合はちゃんと **[テーブルとして書式設定]** しておきましょう。ついでにテーブルにわかりやすい名前を付けておくと **Good👍** です。
**[テーブルとして書式設定]** した後に **[テーブルデザイン]** - **[テーブル名]** で任意の名前を付けてあげてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/533ec028-075b-5f46-c0c1-784a6348a5dd.png)

Excel を保存しておきましょう。

## Power BI Desktop でとりあえず読み込んでみる
**Power BI Desktop** を起動して、保存した **Excel** をデータソースに指定して、読み込みましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/6303f3ef-978d-cc34-7c09-d109869b74d5.png)
**Excel** を読み込む導線はいくつかありますが、今回は楽をして、デフォルトで表示されるキャンバスのタイル**「Excelからデータをインポートする」**から行きましょう。
先ほど保存した **Excel** ファイルを選択して、開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/44ce7959-80b2-3a36-7691-b1d9b13c9f2e.png)
**[ナビゲーター]** が開きます。
ここで先ほど **Excel** で **[テーブルとして書式設定]** して名前を付けておいてよかったと思うわけです。ちゃんとテーブルに付けた名前が認識されているでしょ？

**「だから何？」** って思った人。想像してみてください。仕事で使用する **Excel** ファイルはたくさんのシートがありませんか？そして、データがいろんなシートに散在していませんか？仮に **[テーブルとして書式設定]** がされていても、名前を付けていないと「テーブル1」「テーブル2」... とナンバリングされた名前が付いてしまいます。そうなると、このナビゲーター画面でどのテーブルを選んでよいか、まるでわからないことになります。

そうならないように、普段から Excel に再利用したいデータを入れる時は

:::note info
**「テーブル形式にして、[テーブルとして書式設定] して、名前を付ける」**
:::

と癖付けしておくと、お仕事で困る要素がひとつ防げるかもしれません😇

横道に逸れました。本題に戻って、こんなふうにデータが読み込めたはずです。
画像はデータビューです。データビューは画面左側の縦に3つ並んでいるアイコンの真ん中をクリックすると表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/8e4a0d3d-62a7-f339-d4e5-dd2f2a5bb275.png)

## DAX で計算列を作成する
次に **DAX** でフルネームを格納する列を作成してみましょう。具体的には **[新しい列]** をクリックして作成します。
**[新しい列]** をクリックして作成する列を **計算列 (Calculated Column)** と呼びます。この用語は覚えておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/339d8391-1be5-cbcd-92a7-6a30ed2143c7.png)
**[新しい列]** をクリックして、画面上部の数式バーに次のように入力すると、簡単に文字列連結をした結果を新しい列として、保持することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/3d0b11b9-c41f-4557-3977-9f5dee4f8d30.png)

```Power Query:計算列 - Full Name DAX
Full Name DAX = [First Name] & " " & [Last Name]
```

これに関しては Excel でも同じ感じですよね。これが DAX でやった場合です。ただ、今回の例で言うと、**最下流で変換を行った** ことになります。

ここでもう一度先ほどの言葉を思い出しましょう。

:::note info
Data should be transformed as far upstream as possible, and as far downstream as necessary.
データは、可能な限り上流で変換し、必要に応じて下流で変換されるべきだ。
:::

ということで、次は Power Query で同様の変換をやってみましょう。

## Power Query でやってみる
次は **Power Query** でやってみましょう。
リボンの **[ホーム] - [データの変換]** をクリックして、**Power Query エディター** を起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/ad5306c8-0f31-dce2-38d4-be2250dfb364.png)
**Power Query エディター** が起動したら、リボンの **[列の追加] - [カスタム列]** をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/c98cd596-114f-b5df-e631-a6cf9c883778.png)
カスタム列を作成する画面で以下のように入力してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/ef3e97fc-d9c9-b19d-a10d-454b0a6419e2.png)
上記のように、**[新しい列名]** と **[カスタム列の式]** を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/e1b2d759-bbb5-b831-dd67-963ac35e1156.png)
すると、**[Full Name Power Query]** という列ができ、フルネームを格納することができました。ただ、列名の左を見ると ABC と 123 が上下に表示されています。ここ列の型を表すアイコンが表示されるのですが、この状態は **type any** と呼ばれる型です。簡単に言うと「なんでもあり」という型なのですが、**type any** のままでデータを読み込むことは推奨されていない（ベストプラクティスではない）ので、列名の左側をクリックして、型を指定しましょう。当然今回は文字列 (テキスト) ということになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/bbd1f5e2-7575-73cc-c129-dfc6d49dcd80.png)
これで無事に Power Query で文字列連結をすることができましたので、リボンの **[ホーム] - [閉じて適用]** をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/e8cf6254-801a-9651-48a4-7507abb63e60.png)

**Power BI Desktop** に戻ってきたら、先ほど **DAX** で作成した結果と同様の結果が得られていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/9a633622-7b68-e6e6-bd83-3f351dbab936.png)

これで先ほど最下流の **DAX** で行った変換をひとつ上流に委ねることができました。

# **下流で変換を行うことはダメなのか？**
ここまでの内容を見て、皆さんの頭にはこんな疑問が湧いているかもしれません。ポイントは **「必要に応じて下流で変換されるべき」** という部分だと、私は考えています。

## 観点1：効率的
まず一般的に言って、データの変換が上流であればあるほど、マシンリソースが潤沢なので、処理が早く終わる可能性があります。

最も単純に考えると、例えばデータソースが **DB (データベース)** だった場合、DB 側で BI が要求する形でデータを保持していてくれたら、データ変換はひとつも要らないということになります。これが最も効率的なことは容易に想像がつくことでしょう。下流に行けば行くほど、本来必要としている形ではないデータ形式で、大量のデータを取得して、大量のデータを必要な形に変換する必要が出てきます。

## 観点2：統一されたデータの実現
組織において、**みんなが同じデータを扱う**というのはとても大事な話です。**部署Aが見ている「売上」データと部署Bが見ている「売上」データの値が異なるなんてことは、絶対にあってはならない**わけです。全社的に必要なデータは、レポートという形で**トップダウン**で提供する。これが **エンタープライズBI** です。この場合、提供元の部署以外、どの部署の人であっても、みんながユーザーとなります。ユーザーは提供されたレポートを見て、自分で分析します。自分でデータを弄って、再度新たなレポートを作成することはしません。まして、元データを情報システム部門に要求してしまっては、本末転倒ということになります。

一方、各部署で独自に保有しているデータというのも存在しています。全社的に提供されたデータと、自部署特有のデータを掛け合わせて、自部署にとって有効なレポートを作成したい場合があります。これが **セルフサービスBI** ということになります。究極的には、担当者個人が自分だけのレポートを作ることもあるかもしれません。それがチーム **MTG** で共有されて、チームメンバーの目を引いた場合、そのチームの標準レポートになるかもしません。もしそのレポートを偶然に目にした隣の部署が欲しいと言ったら、レポートを共有すればいいわけです。このように**ボトムアップ**で広がっていく可能性があるのが **セルフサービスBI** です。

さて、**エンタープライズBI** にしろ、**セルフサービスBI** にしろ、同じデータを必要とする複数の人がいるというケースはごく自然のことです。

いま、商品マスタと売上データを利用して、レポートを作成したいと思っている A さんと B さんがいるとしましょう。システムに格納されている商品マスタはそのままでは使用できず、データ変換が必要な状態です。売上データもシステムに格納されているままでは、情報が多すぎる（余計な列を持っている）ので、BI には向きません。また、A さんと B さんは所属部署が異なり、レポートを作成する目的が異なります。従って、最終的に必要とするデータの形も微妙に異なります。ただ、現時点で商品マスタについては、共通のデータで問題ないということがわかっており、売上データについては、少なくとも A さんも B さんも必要ない項目が判明しています。

こういった場合、A さんと B さんがそれぞれに元のデータを取得して、例えば **Power Query** で変換してしまうと、本人たちは問題がないように見えますが、会社としては非効率だということがわかります。商品マスタについては、同じ変換をそれぞれ **Power Query** で行ってしまうわけですからね。また、もし B さんが **Power Query** を得意としていない場合、変換処理を間違えて、正しくない結果を保持してしまうリスクもあるわけです。

つまり組織において **「統一されたデータ」** とは、

- 誰でも使用できる
- 変換が不要で即座に BI で使える
- その企業特有の考え方が既に反映されている

状態が望ましいということになります。

これを実現するには、やはり **可能な限り上流でデータ変換を行う必要がある** というわけです。
その組織の人がデータを見たら **「あ、データ変換不要じゃん！すぐに使えるじゃん！！」** と思える必要があるのです。

## 観点3：理想はわかるが、とは言っても...
観点1 と 2 を踏まえた上で、それでもなかなかにそれらの理想を達成するのは容易ではありません。そこに至らないと **BI** が使えないということでは、ビジネスに乗り遅れてしまう可能性もあります。ですので、**「必要に応じて下流で変換すべき」** ということになるのです。

データ変換が不要な状態でデータがシステム部門より提供されていれば問題ないですが、このご時世、情報システム部門はなかなかに多忙なこともありますし、何より **BI** に必要なデータ形式がわかる人がいないということもあるでしょう。そういった場合、とりあえずデータを提供して、下流にてデータ変換をする必要が出てくることもあるわけです。効率を考えたら、ベストではないですが、ビジネスは待ってくれません。いま優先すべきことを天秤にかけた結果、下流にてデータ変換をすれば、なんとかなる可能性があるのであれば、トライしてみるのもアリかもしれません。ただし、その場合でも、ベストプラクティスである

:::note info
Data should be transformed as far upstream as possible, and as far downstream as necessary.
データは、可能な限り上流で変換し、必要に応じて下流で変換されるべきだ。
:::

は変わりませんので、**最上流でいつ対応できるのか？** について、話し合って、予定しておく必要はあるでしょう。

# 最後に
さて、話を戻しましょう。
ここまできたら、勘のいい方は既にお気付きかもしれません。

**「ってことはさ、さっきのExcelの例って、Power Query でやるよりも、Excel で対応しちゃえばいいんじゃないの？」**

こう思われた方がいらっしゃったら、素晴らしい。大正解です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152946/441a24b7-9341-f486-d75c-c49192be9619.png)

これが今回のケースで言うところの**最上流で対応した場合、つまりデータソース側で対応した**ということになるのです。

# 決まり文句
**みなさんの Power BI Life がより良いものになりますように📢**