グループ化と集計
グリッドは、行の代わりにグループを表示できます。キーの列の値の組み合わせごとに 1 行で、グループごとの集計値(個数・合計・平均など)を並べます。グループ化していないビューでは、表の下端に集計行も表示できます。どちらもエンジンが表全体について計算するので、1 億行の表でもブラウザーに届くのはグループだけです。
グループ化したビューは、プランの aggregate です。グループ化に対応するエンジンは capabilities.plan.aggregate を、ピボットに対応するエンジンは capabilities.plan.pivot を、グループを条件で絞り込めるエンジンは capabilities.plan.having を返します。メモリーエンジンと DuckDB エンジンはどれにも対応していて、結果も同じです。
グリッドでの操作
Section titled “グリッドでの操作”- 列のメニューの この列でグループ化 は、その列だけをキーにしてグループ化し、行を数えます(
count(*))。グループ化したビューでは、キーの列のメニューに「この列でのグループ化をやめる」が出て、「グループ化を解除」で行の表示に戻ります。 - ツールバーの グループ メニューでグループ化を編集します。変更はすぐに反映します。
- 「グループ化する列」:キーの列を順に並べ、「列を追加…」で足します。
- 「集計」:集計方法と列(行を数えるときは「(行)」)を選び、追加します。集計値の列名は 0.1 と同じく
sum(qty)、count(*)のように付きます。 - 「値を列にする列」(エンジンがピボットに対応するとき):値を列にする列を選びます(ピボットを参照)。
- グループ化したビューの列は、キーの列、続けて集計値ごとの列です。どの列でもほかのビューと同じように並べ替えられます。検索欄と条件メニューは、グループ化する前の行を絞り込みます。
- 計算列は行をグループ化する前に計算するので、キーにも集計する列にもできます。
- グループは表の行ではありません。行 ID がなく、セルに書き込めず、絞り込み…・統計…・集計行も出ません。ビューを書き出すと、グループを書き出します。
チャートのガイドでは、グリッドが表示しているグループをチャートに描きます。
| 集計方法 | 列 | 結果 |
|---|---|---|
個数(count) |
指定しなければ行の数、指定すればその列の null でない値の数 | 整数 |
異なる値の数(count_distinct) |
順序のある列 | 整数 |
合計(sum) |
数値の列 | 整数と decimal は正確な値、浮動小数点数は浮動小数点数 |
平均(avg) |
数値の列 | 浮動小数点数。正確な合計から計算する |
標準偏差(stddev) |
数値の列 | 浮動小数点数。標本標準偏差 |
最小・最大(min・max) |
順序のある列(数値・文字列・真偽値・日付と時刻・UUID) | 列と同じ型。列の書式で表示する |
分位数(quantile) |
数値・日付・時刻の列。p は 0〜1 |
いちばん近い 2 つの値の間を補間する。浮動小数点数か、マイクロ秒までの時刻(日付ならタイムスタンプ) |
分位数はコードから指定します。グループメニューではそれ以外を選べます。
- 集計では null を除きます。浮動小数点数の列では、個数以外の集計で NaN と無限大も除きます。
- 値が 1 つもないとき、個数と異なる値の数は 0、ほかの集計は null です。
- キーの値の組み合わせごとに 1 つのグループになります。null と空の文字列は別々のグループで、NaN はすべて 1 つのグループです。
- 並べ替えないときは、キーの昇順に並びます。空の文字列は null より前です。
規則は仕様の §3.8 と §3.9 にあり、どのエンジンでも同じです。
ピボットはクロス集計表を作ります。キーの列の後に、ピボットする列の値の組み合わせごとの列が続き、それぞれに集計値が入ります。キーを region、ピボットする列を city と year、集計値を sales にすると、列は region、Tokyo / 2024 / sales、Tokyo / 2025 / sales のようになります。null は (null)、空の文字列は (empty) と書きます。行のないセルは、個数なら 0、それ以外は null です。
ピボットで作る列は maxColumns 個までです(既定は 200、最大 1,000)。それより多くなるプランは、途中で切らずに too_many_columns で失敗します。グリッドは前のビューを表示したままにし、ステータスバーに理由を表示します。ピボットの列はデータから決まるので、並べ替えと having に使えるのはキーの列だけです。
グループに対する条件
Section titled “グループに対する条件”having は、where が行を絞り込むのと同じように、条件が真になるグループだけを残します(例:注文が 10 件以上の地域)。コードから having.set で指定し、グループ化したビューでだけ使えます。キーと集計値を列名で参照します。
列のメニューの「集計行…」で、その列の集計方法を選び、表の下端の行に表示します。選べるのは合計・平均・個数・異なる値の数・最小・最大のうち列の型に合うものと、「集計しない」です。行をスクロールしても集計行は見えたままで、メニューの項目は選んだ集計方法(「集計行: 合計」)を表示します。
集計の対象はビューのすべての行(絞り込みと検索の結果で、選択範囲ではありません)で、ビューや書き込んだセルが変わるたびに計算し直します。集計方法はドキュメントの列の設定に保存され、値はスナップショットの totals に入ります。グループ化したビューには集計行を表示しません。
コードから使う
Section titled “コードから使う”メニューはコマンドを送ります。アプリからも同じコマンドを送れます。
await store.dispatch({ command: "group.set", aggregate: { keys: ["region"], measures: [ { name: "orders", fn: "count" }, { name: "sales", fn: "sum", column: "total" }, { name: "median price", fn: "quantile", column: "price", p: 0.5 }, ], },});await store.dispatch({ command: "having.set", having: { fn: "ge", args: [{ col: "orders" }, { lit: 10 }] } });await store.dispatch({ command: "column.total", name: "total", total: { fn: "sum" } });await store.dispatch({ command: "group.clear" });| コマンド | 引数 |
|---|---|
group.set |
aggregate:keys、measures({ name, fn, column?, p? })、pivot({ columns, maxColumns? }) |
group.clear |
なし。行の表示に戻す |
having.set |
having:条件か null |
column.total |
name と、total:{ fn, p? } か null |
プランに aggregate を持つドキュメントから始めれば、最初からグループ化して表示できます(状態を参照)。
import type { GridDocument } from "vastgrid";
const byCategory: GridDocument = { kind: "vastgrid/document", version: 2, plan: { aggregate: { keys: ["category"], measures: [{ name: "sales", fn: "sum", column: "total" }] }, sort: [{ column: "sales", direction: "desc" }], },};