なんでもエクセル(Nandemo Excel)

何でもエクセルでやってしまう そこのあなた。ようこそ

Poewr Query:累計を計算する

クエリでやるのがそこそこ面倒なのが「上のセル(もしくは下のセル)との比較」である。累計は「上のセルの値を足していく」処理なので、どうしても上下位置を指定して値を取得する必要がある。安直な方法だと処理が重くなるので注意。

今時、Microsoft365なら数式で何ら困らない処理なんだけども……

数式版:Microsoft365の場合
=LET(
    _rng,テーブル1[数値],
    _hd,"累計",
    _bd,SCAN(0,_rng,LAMBDA(x,y,x+y)),
    VSTACK(_hd,_bd)
)

LAMBDA関数内で定義している「x」が初期値にあたるので、ここに「0」を入れておいて配列の計算結果を戻入していく。VSTACKは見出しを付けただけなので、ほぼおまけ。

クエリで処理する場合、「累計」と聞いて思い付くのは「List.Accumulate」ではないだろうか。ひとまず「数値」列を内包する「テーブル1」クエリは作成済とする。

クエリ版:List.Accumulateを使う場合
    数値リスト = テーブル1[数値],
    リスト生成 = List.Accumulate(
        数値リスト, {0}, (x, y)=>{y + x{0}} & x
    ),
    テーブル変換 = Table.FromColumns(
        {List.Skip(List.Reverse(リスト生成))},
        type table [累積=Int64.Type]
    )

こうして見ると、ワークシート関数の SCAN関数とよく似ているのが分かる。ここでは変数「y」が初期値にあたる。変数「x」がリストなので、「x{0}」で値にしてから足す手間が発生しているだけで、やっていることはほぼ変わらない。「List.LastN」を使わないのは、これをやるとデータ全体の読み込みがかかるのでデータ量によってはとてつもなく重くなるから。Power Queryでは基本「上から必要な部分までを抜き出す」ほうが処理が軽い。

続いて、連番を用意して「List.FirstN」を使う方法。

クエリ版:List.FirstNを使う場合
    数値リスト = テーブル1[数値],
    累計 = List.Transform({1..List.Count(数値リスト)},
        each List.Sum(List.FirstN(数値リスト, _))
    ),
    テーブル変換 = Table.FromColumns(
        {累計}, type table [累計=Int64.Type]
    )

5000行くらいで試してみたところでは、あまり速さに違いはなかった。どっちがいいかは状況判断かと思う。