Power BIでデータをフィルタしながら計算する方法 ~ Calculate関数 ~
本記事でわかること
Calculate関数の書き方と説明
CALCULATE(<式>, <フィルター1>, <フィルター2>, …) は、
フィルターをかけながら計算を行える、DAXで最重要の関数です。
「文脈(コンテキスト)」を操作できるため、普通の SUM や AVERAGE ではできない計算が可能になります。
CALCULATE関数の書き方
//フィルター条件に合う行だけを対象に、計算式を実行
CALCULATE(
計算式,
フィルター条件
)
または
//フィルター条件に合うテーブルを再定義して、それに対して計算式を実行
CALCULATE(
計算式,
FILTER(テーブル, フィルター条件)
)
使用例
例1:特定カテゴリを除外して計算したい場合
その他カテゴリ売上 =
CALCULATE(
SUM('Sales'[金額]), //計算したい式
'Sales'[カテゴリ] <> "その他" //ここがフィルター条件 (カテゴリが「その他」以外、など)
)
👉 「カテゴリ"その他"を除外して」売上合計を計算
例2:累計計算をしたい場合
累計売上 =
CALCULATE(
SUM('Sales'[金額]), //計算したい式
FILTER(
ALL('Sales'[日付]),
'Sales'[日付] <= MAX('Sales'[日付]) //ここがフィルター条件 (グラフ上の現在の日付以下、など)
)
)
👉 ALLで全日付を無視 → 「(グラフ上の)現在の日付以下」で累計を実現
※FILTER()を使って対象テーブルを再定義することで、ページやビジュアル上のフィルターをリセットし、全てのデータを改めて対象にできます。
このようにテーブルを再定義してその中で計算したいときや、「売上が平均より大きい行だけ」のように動的に計算した値との比較をしたい場合は FILTER() が必要です。
「あれ?エラー出る/思った結果にならない」と思ったら FILTER 付きに切り替えると良いです。
よく使うALL系関数
CALCULATE関数とFILTER関数を組み合わせて使うとき、ALL系関数が役立ちます。
これは、ページやビジュアルに既にかかっているフィルターの一部/全部を除去するための便利な関数です。
例えば「ページ上で既にかかっているフィルターを除きたい」「でも特定のスライサーは効かせておきたい」ときなどに使えます。
よく使うALL系関数一覧
- ALL(テーブル/列) → フィルターをすべて無効化
- ALLEXCEPT(テーブル, 列1, 列2…) → 指定した列のフィルターだけ保持。それ以外を除外。
- ALLSELECTED(列1, 列2…) →
指定した列のフィルターだけ除外。それ以外を保持。
※ALLSELECTED()は挙動が特殊なので、できればALLEXCEPT()で対応したい
例1: ALL のユースケース → 「前年比の売上」
特定の年だけでなく、すべての年を比較対象にしたいとき
前年比売上 =
CALCULATE(
SUM('Sales'[金額]),
FILTER(
ALL('Sales'), //Salesテーブルのフィルターを一旦すべて外す!
YEAR('Sales'[日付]) = YEAR(MAX('Sales'[日付])) - 1 //グラフ上の現在の年の前年にフィルタ、など
)
)
- ALL('Sales') → ページやビジュアルのフィルターを無視して「前年のデータ」を取る
- フィルターを一度外さないと、例えばグラフ上で今年を参照している場合「今年」に縛られて前年を参照できない
例2: ALLEXCEPT のユースケース → 「製品ごとの市場シェア」
各製品の売上を「全体売上」に対して比較したいとき
カテゴリ別売上合計 =
CALCULATE(
SUM('Sales'[金額]),
FILTER(
ALLEXCEPT(
'Sales',
'Sales'[製品カテゴリ] //「製品カテゴリ」列のフィルターだけ残して、それ以外のフィルターをすべて外す!
)
)
)
- ALLEXCEPT('Sales', 'Sales'[製品カテゴリ]) → 製品カテゴリのフィルターは残すが、その他のフィルターはリセット
- 「カテゴリ内での売上」といった分析に使える
例3: ALLSELECTED のユースケース → 「スライサーで選択した期間内の累計売上」
ユーザーがスライサーで期間を選んで、その範囲内で累計を見たいとき
選択期間内の累計売上 =
CALCULATE(
SUM('Sales'[金額]),
FILTER(
ALLSELECTED('Sales'[日付]), //「日付」列にかかるフィルターだけ除去して、それ以外は残す!
'Sales'[日付] <= MAX('Sales'[日付]) //改めて必要なフィルタを指定(現在の日付以下、など)
)
)
- ALLSELECTED('Sales'[日付]) → スライサーで指定された範囲だけ残る
- その範囲の中で累計を計算できるので「四半期や任意期間での累計」が出せる
Tips
- Calculate関数を「フィルターをつけて計算する魔法の器」と覚える
- ALL系関数と組み合わせると表現の幅が広がる
- 普通にSUMで出せないものは、だいたいCALCULATEで解決できる
設計レビューや式の相談もお気軽にどうぞ。