_(アンダースコア)の正体を一言でいうと何か
Power Query(M言語)で使われる _ は、「無名関数の引数として自動的に渡される“現在の値”を表す特別な変数」です。 もっと噛み砕くと、
_ は “今まさに処理している値そのもの” を指す記号
だと理解すると一気に分かりやすくなります。
ただし、ここでいう「値」は、
- 行全体(record)
- 列のセル値
- リストの要素 など、使う関数によって変わります。
つまり、_ は「その場で処理対象になっているもの」を指す万能の“現在値”変数なのです。
_ は「無名関数の引数」の省略記法
無名関数の“素の形”を先に見てみる
まず、無名関数を普通に書くとこうなります。
(x as number) as number => x * 2
Power Queryここでの x が「引数」です。 この関数をリストに適用すると、各要素が2倍になります。
List.Transform({1,2,3}, (x as number) => x * 2)
Power Queryこれを _ を使って書くとこうなります。
List.Transform({1,2,3}, each _ * 2)
Power Queryつまり、
_は「無名関数の引数」each _ * 2は「(x) => x * 2」の省略形
という関係になります。
ステップバイステップで _ の意味を理解する
ステップ1:_ は「今処理している値」を指す
例:リストの各要素を2倍にする
List.Transform({1,2,3}, each _ * 2)
Power Queryここでの _ は、
- 1回目:1
- 2回目:2
- 3回目:3
というように、リストの各要素そのものを指します。
ステップ2:テーブルの列変換では「セルの値」を指す
Table.TransformColumns の中で使う _ は、 その列のセル値を指します。
Table.TransformColumns(
SalesTable,
{
{
"顧客名",
each Text.Upper(_),
type text
}
}
)
Power Queryここでの _ は、
- 「顧客名」列の各セルの値 を指します。
つまり、
行ではなく “列のセル値” を処理する場面では _ が使われる
ということです。
ステップ3:行全体を扱う場合は _ が「行(record)」になる
Table.AddColumn や Table.SelectRows の each の中では、 _ は行全体(record)を指します。
例:
Table.AddColumn(
SalesTable,
"金額2倍",
each _[金額] * 2,
type number
)
Power Queryここでの _ は、
- 行全体(record) であり、
_ [金額]でその行の金額列を参照しています。
つまり、
_ は「行を表す record」になることもある
ということです。
_ の意味は「使う関数によって変わる」
代表的な関数と _ の意味の対応表
| 関数 | _ が指すもの | 例 |
|---|---|---|
| List.Transform | リストの各要素 | _ * 2 |
| Table.TransformColumns | 列のセル値 | Text.Upper(_) |
| Table.AddColumn | 行全体(record) | _ [金額] * 2 |
| Table.SelectRows | 行全体(record) | _ [金額] > 1000 |
この表を覚えておくと、 「今この _ は何を指しているのか?」 が迷わなくなります。
_ を使った実務的な例
例1:リストの値を加工する(_ は要素)
let
Numbers = {1, 2, 3},
Doubled = List.Transform(Numbers, each _ * 2)
in
Doubled
Power Query例2:列の値をクレンジングする(_ はセル値)
Table.TransformColumns(
SalesTable,
{
{
"顧客コード",
each Text.Upper(Text.Trim(_)),
type text
}
}
)
Power Query例3:行全体を使って判定する(_ は record)
Table.SelectRows(
SalesTable,
each _[金額] <> null and _[金額] > 1000
)
Power Query例4:行全体を関数に渡す(_ は record)
Table.AddColumn(
SalesTable,
"有効行",
each IsValidRow(_),
type logical
)
Power Query_ を使うときの重要な注意点
1. _ が「行」なのか「セル値」なのかを必ず意識する
間違いやすい例:
Table.AddColumn(
SalesTable,
"顧客名大文字",
each Text.Upper(_)
)
Power Queryこれはエラーになります。 なぜなら _ は「行全体」であり、 Text.Upper(record) はできないからです。
正しい書き方:
each Text.Upper(_[顧客名])
Power Query2. _ を使いすぎると読みづらくなる
複雑な処理は関数に切り出した方が安全です。
悪い例:
each if _[金額] > 1000 and Text.Length(_[顧客コード]) > 3 then true else false
Power Query良い例:
each IsHighValueCustomer(_)
Power Query3. セキュリティ・品質に関わる処理を _ の中に直接書かない
権限判定や重要顧客判定などは、 必ず関数に切り出しておくべきです。
理由:
- ロジックのレビューがしやすい
- 誤って条件を緩める事故を防げる
- 意図が明確になる
実務で使える「_」テンプレート
テンプレ1:列の値を加工する
Table.TransformColumns(
SalesTable,
{
{"顧客名", each Text.Upper(_), type text}
}
)
Power Queryテンプレ2:行全体を使って判定する
Table.SelectRows(
SalesTable,
each _[金額] > 1000
)
Power Queryテンプレ3:行全体を関数に渡す
Table.AddColumn(
SalesTable,
"有効行",
each IsValidRow(_),
type logical
)
Power Queryまとめ:_ を理解することは「無名関数の仕組み」を理解すること
M言語で _ の意味を理解するというのは、 「無名関数が何を引数として受け取っているか」を理解することでもあります。
_ は、
- リストの要素
- 列のセル値
- 行全体(record)
など、使う関数によって姿を変える「現在値」を表す記号です。
ぜひ、
- 「_ はその場で処理している値」
- 「行なら
[列名]、セルなら_」 - 「複雑な処理は関数に切り出す」
という感覚を身につけて、 実務の Power Query をより読みやすく、安全で、意図の伝わるコードに育てていってください。
