【VBAリファレンス】Power QueryのM言語で実現するグループ内最小・最大値の抽出術:データ分析の生産性を劇的に高める高度なテクニック

スポンサーリンク

概要:なぜPower Queryでの「グループ内集計」が重要なのか

ExcelのVBAや関数を使いこなす実務家にとって、膨大なデータから「カテゴリごとの最大値・最小値」を抽出する作業は日常茶飯事です。しかし、従来のVLOOKUPやピボットテーブル、あるいはVBAによるループ処理では、データ量が増加するにつれて処理速度が低下したり、メンテナンスが困難になったりする課題がありました。

そこで注目すべきが、Excelの標準機能である「Power Query」と、その裏側で動作する「M言語」です。Power Queryは、BIツールとしての側面を持ちながら、Excelのデータ加工エンジンとして最強のパフォーマンスを誇ります。特に「グループ化(Group By)」の概念を理解し、M言語の数式を少しカスタマイズするだけで、複雑な条件付きの最小値・最大値抽出が驚くほど簡潔に実現できます。本記事では、この高度なテクニックをプロフェッショナルな視点から徹底解説します。

詳細解説:Power Queryにおけるグループ化のロジック

Power QueryのUI上では、「グループ化」ボタンを押すことで、指定した列ごとに「合計」「平均」「最小」「最大」を算出できます。しかし、実務では「単にカテゴリごとの最大値を知りたい」だけでなく、「最大値を持つ行全体のデータが欲しい」というケースがほとんどです。

標準のUI操作で「グループ化」を行うと、集計結果のみが表示され、元の行データが失われてしまいます。ここで必要になるのが、M言語の強力な関数である「Table.Group」と、行全体を保持するための「レコードの抽出」のテクニックです。

M言語の「Table.Group」関数は、以下のような構造をしています。
Table.Group(ソーステーブル, グルーピング列名, {{“新しい列名”, 集計関数}})

通常、集計関数には「List.Max」や「List.Min」を指定しますが、これに加えて「各グループ内の全データを保持したテーブル」を一度作成し、そこから特定の列の最大値に対応する行を抽出するというアプローチが、M言語における「グループ内最大・最小抽出」の王道となります。

サンプルコード:M言語による実践的実装

以下は、ある店舗ごとの売上データから「各店舗の中で売上が最大だった日のデータ」を抽出する際のM言語コードです。このコードを詳細エディタに貼り付けることで、その仕組みを理解できます。


let
    // サンプルデータの読み込み
    Source = Table.FromRecords({
        [店舗 = "東京", 日付 = #date(2023, 1, 1), 売上 = 5000],
        [店舗 = "東京", 日付 = #date(2023, 1, 2), 売上 = 8000],
        [店舗 = "大阪", 日付 = #date(2023, 1, 1), 売上 = 9000],
        [店舗 = "大阪", 日付 = #date(2023, 1, 2), 売上 = 4000]
    }),

    // 店舗ごとにグループ化し、各グループの「全データ」をテーブルとして保持
    GroupedRows = Table.Group(Source, {"店舗"}, {{"全データ", each _, type table}}),

    // 各グループのテーブルに対し、売上が最大の行を抽出する処理を追加
    // each Table.Max([全データ], "売上") と記述することで、最大値行を特定
    Result = Table.AddColumn(GroupedRows, "最大売上の詳細", each Table.Max([全データ], "売上")),

    // 不要な列を削除し、レコードを展開
    RemovedOtherColumns = Table.SelectColumns(Result,{"最大売上の詳細"}),
    ExpandedData = Table.ExpandRecordColumn(RemovedOtherColumns, "最大売上の詳細", {"店舗", "日付", "売上"}, {"店舗", "日付", "売上"})
in
    ExpandedData

このコードの肝は、「Table.Group」の集計関数部分で「each _」と記述し、テーブルそのものを保持している点です。これにより、単なる数値の最大値だけでなく、その最大値が発生した「日付」や「担当者」などの付随情報を、一切のループ処理を書くことなく一瞬で抽出できます。

実務アドバイス:パフォーマンスとメンテナンス性の向上

VBAで同様の処理を行おうとすると、Dictionaryオブジェクトを用いてカテゴリごとにキーを生成し、ループ内で比較処理を書く必要があり、コード量が膨大になりがちです。また、メモリ管理を誤ればExcelがフリーズするリスクもあります。

一方、Power Query(M言語)を用いた場合、以下のメリットが得られます。

1. 非破壊的なデータ加工:元のデータソースを変更することなく、変換プロセスのみを記録できるため、エラーが発生しても即座に修正可能です。
2. 自動再計算:データソースのExcelテーブルを更新し、「すべて更新」ボタンを押すだけで、最新データに基づいた最大値・最小値の抽出が自動で行われます。
3. 大規模データへの耐性:数万行を超えるデータであっても、Power Queryのエンジンは最適化されているため、VBAよりも高速に動作することが多々あります。

実務で活用する際は、「Table.Max」や「Table.Min」だけでなく、複雑な条件が必要な場合は「Table.Sort」を併用するのも有効です。特定のグループ内を日付順に並べ替え、その「最初の行(Table.First)」を取得するというロジックに置き換えることで、条件分岐の柔軟性がさらに高まります。

また、M言語の関数は「大文字と小文字を区別する」点に注意してください。関数名や列名は正確に記述する必要があります。数式バーでの入力が不安な場合は、GUIで「グループ化」を作成した後、数式バーを直接編集して「each Table.Max(…)」の形に書き換える手順を踏むことを強く推奨します。

まとめ:M言語を武器に「データ抽出」の達人へ

Power QueryのM言語を習得することは、単なる「便利な機能を使う」こと以上の価値があります。それは、データ分析における「思考の枠組み」を広げることです。

「グループ内の最小・最大を抽出する」という単純なタスクを、M言語の関数型プログラミングのスタイルで解決できるようになれば、他の複雑なデータクレンジング作業にもその応用が効くようになります。VBAのループ処理に頼り切りだった日々から脱却し、より宣言的で保守性の高いデータパイプラインを構築しましょう。

今回のテクニックは、レポート作成や異常値検知、あるいはKPIのモニタリングにおいて、間違いなくあなたの強力な武器となるはずです。まずは手元の小さなデータセットでこのコードを試し、Power Queryが持つ圧倒的な処理能力と柔軟性を肌で感じてください。Excel業務の未来は、間違いなくこの「M言語」の先にあります。

タイトルとURLをコピーしました