ggsql - SQLのためのグラフィック文法
(opensource.posit.co)- SQL文法ベースの可視化ツールで、
VISUALIZE、DRAW、PLACE、SCALE、LABELのような句を通じて、データ取得とグラフ構成を1つの流れに統合 - 列を視覚属性にマッピングし、レイヤー合成方式によって散布図、棒グラフ、ヒストグラム、箱ひげ図、注釈要素まで同じ構造の中で構成可能
- SQLクエリ結果をそのまま可視化入力へ渡し、一部のレイヤーは単一のSQLクエリ実行で集計だけを取得する構造のため、大規模データ処理に有利
- RやPythonランタイムなしでも使える小さく集中した実行ファイルを志向した設計で、コードベースのレポートツールやAI分析アシスタントとの統合にも適性を示す
- 現在のバージョンはalpha-releaseであり、高性能writer、テーマ、インタラクティビティ、language server、formatter、空間データ対応などの拡張計画を提示
ggsqlの紹介
- ggsqlはSQL文法ベースのgrammar of graphics実装で、SQLに構造化された可視化機能を追加
- Quarto、Jupyter notebooks、Positron、VS Codeなどで利用可能
- SQLユーザーにとって馴染みのある方法で可視化コードを書けるように設計されている
- SQLの宣言的で組み合わせ可能な句構成を可視化文法にも適用
- 動機と使用例をあわせて示しながら、ggsqlの中核構文を展開
基本例
-
最初のプロット
- 組み込みの
penguinsデータセットで散布図を作成可能VISUALIZE bill_len AS x, bill_dep AS y FROM ggsql:penguinsDRAW point
VISUALIZEでデータ列を視覚属性にマッピングし、DRAW pointがその基本マッピングを使って点レイヤーを生成species AS colorを追加するだけで色のカテゴリ分けを適用可能VISUALIZE bill_len AS x, bill_dep AS y, species AS color FROM ggsql:penguinsDRAW point
DRAW smoothを追加すると、点レイヤーの上に回帰線レイヤーを重ねられる- 種別ごとの色マッピングが維持されるため、speciesごとに別々の線が生成される
- あらかじめ決められたプロット種類ではなく、モジュール型コンポーネントの組み合わせ方式を採用
- 同じ構造を保ったまま、まったく異なる可視化へ切り替え可能
VISUALIZE island AS x, species AS color FROM ggsql:penguinsDRAW bar
- 組み込みの
-
完全な例
- 上段は通常のSQLクエリ、
VISUALIZE以降は可視化クエリとして区別される- 例ではDuckDBバックエンドを使用
- SQL部分では、
astronauts.parquetから名前ごとの最新のmissionだけを残すためにROW_NUMBER()とQUALIFYを使用 - 続いて2つの集合を結合
year_of_selection - year_of_birthをageとして計算し、Age at selectionカテゴリを付与year_of_mission - year_of_birthをageとして計算し、Age at missionカテゴリを付与- 2つの結果を
UNION ALLで結合
- 可視化クエリでは
age AS x、category AS fillをマッピングした後、DRAW histogramを使用SETTING binwidth => 1, position => 'identity'を指定
PLACE ruleで事前計算した平均位置の注釈を追加x => (34, 44)、linetype => 'dotted'
PLACE textでテキスト注釈を追加x => (34, 44, 60)y => (66, 49, 20)- ラベルには
Mean age at selection = 34、Mean age at mission = 44、John Glenn was 77 on his last mission - the oldest person to travel in space!を含む hjust => 'left'、vjust => 'top'、offset => (10, 0)を指定
SCALE fill TO accentでfillマッピング値をaccentカラーパレットに変換LABEL句でタイトル、サブタイトル、x軸ラベル、凡例ラベルを制御- タイトル
How old are astronauts on their most recent mission? - サブタイトル
Age of astronauts when they were selected and when they were sent on their mission - x軸
Age of astronaut (years) fill => null
- タイトル
- 上段は通常のSQLクエリ、
可視化クエリの構造
VISUALIZE以前は純粋なSQLであり、結果テーブルは表として返されず、可視化入力へ直接渡される- SQL部分で生成されたテーブルやCTEは、可視化クエリから参照可能
- データがすでに可視化に適した形なら、SQL部分は省略可能
VISUALIZE year_of_selection AS x, year_of_mission AS y FROM 'astronauts.parquet'
VISUALIZEまたはVISUALISEは、SQLクエリの終了と可視化クエリの開始を示す- マッピングは列を視覚属性、すなわちaestheticsに結びつける役割を果たす
- 例では
ageがx軸位置、categoryが塗り色に対応
- 例では
DRAWは可視化にレイヤーを追加pointのような単純な型もあれば、histogramのようにビニング集計計算が必要な型もある- レイヤーは定義された順序でレンダリングされる
PLACEはDRAWの兄弟句で、テーブルデータではなくリテラル値を使うannotation専用の句- 例の可視化は、ヒストグラムレイヤー、ルール線annotationレイヤー、テキストannotationレイヤーの3レイヤーで構成される
- 1つのレイヤーが1つのグラフィックオブジェクトにだけ対応するとは限らず、同じ型の複数の個別オブジェクトをレンダリングできる
SCALEはデータ値をaestheticに適した値へ変換する句- 文字列カテゴリを実際の色に変える役割だけでなく、連続変換、break pointの定義、ordinalやbinnedのようなスケール型の設定も可能
LABELはタイトル、サブタイトル、軸タイトル、凡例タイトルなどのテキストラベルを追加・変更する機能を提供
一歩引いてみると
- 上の例には多くの構文が含まれているが、中核文法の重要な部分を一度に幅広く含んでいる
- 多くの可視化クエリは、これよりはるかに単純な形で書ける
astronauts.parquetを使った、性別ごとの出生年の箱ひげ図の例を提示VISUALIZE sex AS x, year_of_birth AS y FROM 'astronauts.parquet'DRAW boxplot
- コードの長さは他のプロットシステムより長くなることがあるが、より構造的で、組み合わせ可能で、自己記述的な特性を持つ
- こうした特性によって、あらゆる種類のプロット動作をユーザーが内面化しやすくなり、将来のLLMコーディング支援にも有利になる
- 同じ関係をジッター散布図へ簡単に切り替え可能
DRAW pointSETTING position => 'jitter'
- ジッターがデータ分布に従うよう指定して、violin plot的な性格を持たせることも可能
SETTING position => 'jitter', distribution => 'density'
- このような構文構造と組み合わせ可能性は、探索的分析と可視化設計における反復作業を容易にする
なぜggsqlなのか
- ggsqlを開発した理由として5点を提示
- 主にSQLで作業するデータアナリストとデータサイエンティストを支援する目的
- SQLとgrammar of graphicsの高い相性
- RやPythonのような完全なプログラミング言語なしでも、強力なコードベース可視化ツールを構築する目的
- LLMの優れたSQL処理能力と、新しい可視化インターフェースの可能性
- ggplot2での18年にわたる開発経験を新しい土台に適用しようという意図
-
Hello, SQL user
- データサイエンス革命の中でRとPythonが注目を集める一方、SQLはデータ作業の信頼できる基盤であり続けてきた
- SQLだけ、あるいは主にSQLだけを使うデータワーカーは多数存在する
- 彼らに与えられてきた既存の可視化の選択肢は、本稿の観点では概して最適ではない
- データをエクスポートしてRまたはPythonを使う
- 再現性の支援が不十分なGUIベースのBIツールを使う
- クエリ内で直接使える可視化ツールを使うが、十分に強力でも人間工学的でもないと判断
- ggsqlの文法は、SQLユーザーがすぐ理解できるように設計されている
- 組み合わせ可能で宣言的な句に対する期待を活用
- ggsqlは可視化のやり方を改善するだけでなく、SQLユーザーをQuartoベースのコードベースレポート作成・共有エコシステムへ引き込む役割も果たす
-
宣言的データ加工、宣言的可視化
- SQLは、1つ以上のテーブルに保存された関係データを扱うためのドメイン特化言語
- SQL構文は関係代数の概念に基づき、データ操作を構造的に考える方法を提供する
- SQLの意味論は関数型ではなく、宣言的なモジュール型演算の集合を定義する
- grammar of graphicsは、データ可視化の概念をモジュール型コンポーネントに分解する理論的枠組み
- ggplot2のようなツールがこの概念を実装として具体化した
- grammar of graphicsもまた、関数型というより宣言的なモジュール型演算の集合を定義する
- 両者の体系は、それぞれの領域へのアプローチにおいて大きな共通点があり、生データから最終的な可視化まで自然で強力な全体パイプラインを構成できる
-
No runtime, no problem
- ggplot2にはRのインストール、plotnineにはPythonのインストールが必要
- 一方で、単一で集中した実行ファイルベースの可視化ツールには明確な利点がある
- 他のツールに小さな実行ファイルを組み込むほうが、R/Pythonのバンドルやインストール要求より容易
- スコープが小さいため、悪意ある、あるいは誤ったコード実行をsandboxで制限しやすい
- こうした特性により、ggsqlはAI分析アシスタントや、複数環境でコードを実行するコードベースレポートツールへの統合先として、より魅力的な選択肢になる
- インタプリタ言語から離れることで制約もあるが、得られるものも大きい
- 最も重要な利点は、厳格な構造のおかげで、バックエンド側でレイヤーごとの完全なデータパイプラインを単一のSQLクエリとして実行できる点
- たとえば100億件の取引データでbar plotを描く場合、データウェアハウスから各バーのcount値だけを取得し、100億行全体は取得しない
- boxplotやdensity plotのような、より複雑なレイヤー型にも同じ原理が適用される
- これは、まず全データをマテリアライズしてから計算・描画する大半の可視化ツールと対照的な特性
-
SELECT pod_door FROM bay WHERE closed- LLMは自然言語をSQLへ変換するのに非常に効果的であることが実証されている
- ggsqlにも同じ水準の効果を適用できるのではないかという期待を示す
querychatでは、ggsqlを通じて自然言語ベースの視覚的データ探索がすでに可能- ggsqlはRやPythonより安全で軽量なランタイムであるため、プロダクション環境にコーディングエージェントを展開する際にも、より高い確信を与える
-
We are now wise beyond our years
- ggplot2の18年にわたる開発と保守は、データ可視化文法、使いやすさ、設計に関する18年分の蓄積された思考を意味する
- この知識をすべて再びggplot2へ戻せるわけではない
- 昔に決まった判断やユーザー期待を尊重する必要があり、挑戦するとしても非常に段階的にしか進められない
- ggsqlはblank slate
- ゼロから構築するプロジェクト
- 可視化ツールに対する既存の期待がない環境のために設計されたシステム
- このような出発点が開発プロセスに解放感と活力を与え、それがユーザー体験にも表れていると述べている
未来
- 現在のバージョンはalpha-releaseで、まだ完成していない
- 今後追加したい項目の非網羅的な一覧を提示
- Rustでゼロから書いた新しい高性能writer
- テーマ基盤
- インタラクティビティ
- Posit WorkbenchまたはPositronからConnectまでのエンドツーエンドのデプロイフロー
- 完全なggsql language serverとコードformatter
- 空間データ対応
-
ggplot2開発にはどんな意味があるのか
- ggplot2ユーザーはggsqlの発表を不安と期待が入り混じった視線で見るかもしれないと言及
- Positがggplot2を後回しにしてggsqlへ集中するのかという問いへの答えは違う
- ggplot2はすでに非常に成熟して安定しているが、今後も支援と拡張を続ける計画
- ggsqlの開発過程が、ggplot2へ新機能をもたらすうえでも貢献することを期待
もっと知る
- すぐにggsqlを使ってみたいなら、ggsqlウェブサイトのGetting startedセクションでインストール案内とチュートリアルを確認できる
- ドキュメントページでは、ggsqlがサポートする全機能を確認可能
- ユーザー体験に関するフィードバックを期待しているとの言及を含む
1件のコメント
Hacker Newsのコメント
急いでざっと読んだせいかもしれないが、ブログ記事とドキュメントを見ただけでは、SQLデータベースとの関係が明確に説明されていないように感じた。
最初は、フロントエンドのチャートライブラリが処理するSQL風の可視化DSLくらいのものだと推測していた。
anatomyドキュメントはそのように読めたが、FAQの"Can I use SQL queries inside the VISUALISE clause"には、一部の構文はデータベースに直接渡されると書かれていた。
ホームページには"ggsql interfaces directly with your database"とあるが、実際にどう接続されるのかはよく見えず、混乱した。
ggsqlはデータベースバックエンドに直接接続でき、必要ならインメモリDuckDBでも実行できる。
可視化クエリは、可視化の各レイヤーごとにSQLクエリへ変換され、その結果テーブルをレンダリングに使う仕組みだ。
たとえば
VISUALISE page_views AS x FROM visits DRAW smoothのようなクエリは、データに対するsmoothing kernelを計算するSQLに変換され、返された点を使って最終的な折れ線グラフを描く構造になっている。readerはデータベース接続と、各DB向けのSQL dialect生成を処理する。
現在のalpha段階ではduckdb、sqlite、実験的なODBC reader程度をサポートしており、開発は主にローカルファイルベースのDuckDBを中心に進んでいる。
中核となるアイデアは、可視化クエリを複数のSQLクエリに変換してデータベース上で実行し、返ってきた少量の結果だけでチャートを構成するというものだ。
そのため非常に多くの行があっても、ヒストグラムに必要な統計だけをSQLで計算し、棒の高さを描くのに必要な数個の点だけを受け取ればよい。
デフォルトはインメモリDuckDB接続で、CLIでは
--readerによりディスクファイルやODBC URIへ接続できる。Positronでは"Connections"ペインでより簡単に設定でき、ggsql Jupyter kernelではmagic SQL commentでreaderを指定できる。
ドキュメントでも、こうした外部ツール連携の説明をさらに強化する予定だ。
SQLは宣言的なデータ操作言語であり、データベースの問い合わせによく使われるが、データベースだけに結びついたものではない。
フラットファイル、データストリーム、プログラムメモリ内のデータにもSQLを適用できる。
逆に、SQLなしでデータベースを問い合わせることも可能だと思う。
記事を読み流しながら、なぜこれが必要なのか、そして何の問題を解決するのかという説明を探していたが、あまりピンとこなかった。
リモートSQLデータベースのテーブルをそのまま可視化し、いったんR data frameに持ってきてからggplotを回す段階を減らしたいのかと思った。
しかし、なぜわざわざ新しいSQL類似言語を作るのかも疑問だった。
すでにRにはRとSQLの間を翻訳するdbplyrがあるのだから、むしろggplotがdbplyrのtblオブジェクトを直接サポートし、SQLを生成するよう拡張するほうが直接的ではないかと思った。
あるいはSQL自体が非常に親しまれた言語なので、多くの人がこの文法でggplot系の作業をしたいと考えているのか、とも気になった。
ドキュメントをほぼ全部読んで、ようやくこれがDuckDBとSQLiteバックエンドを持つスタンドアロンの可視化アプリで、現在はVegaliteでレンダリングし、今後さらにバックエンドとレンダラーを増やす計画だと理解した。
下のコメントにあるように、PythonやRを知らないSQL中心のユーザーに可視化を作らせるためのツールに見えた。
もちろん、発表記事がその点をもう少しうまく説明してくれていればよかった、というのには同意する。
私の経験では、アナリスト、科学者、エンジニアが共通して共有している言語は結局SQLであることが多い。
Rでも同じことはできるが、実際のプロジェクトが必ずしもRやPythonで書かれているわけではなく、その代わりSQLデータベースとアクセスエンジンはたいていすでに存在している。
また私はmarimo notebookでバックグラウンドのDuckDBに対してSQLセルをよく使うので、そこでSQLから直接プロットできたら非常に便利だと思う。
最後に、PythonのプロットAPIは覚えて手になじませるのがかなり難しいと感じてきた。
matplotlibで単純なscatterplotを1つ描くだけでもboilerplateが多すぎるので、同じクエリ言語の中に統一された文法があるのはかなり良いと思う。
興味深い点は、特定ライブラリよりもインターフェースとしてのSQLとGoGの形式性の組み合わせにある。
実際のレンダラーやランタイムは重要ではあるが、実装の詳細に近いと思う。
もちろん、同程度の行数のコードでRやPython、matplotlibでも容易にできないことではない。
ただ、そのような環境を悪意ある入力に対して安全にsandboxingするのは難しく、このような宣言的言語なら、信頼していないユーザーがggsqlを入力してもチャートだけを生成する形でホストしやすくなる。
そういう意味では確かに有用だ。
ただ、一般的な利用の多くでは、お気に入りのLLMにmatplotlibコードを生成させるほうが簡単な選択かもしれない。
プロジェクト自体は応援しているし、この概念がSQLに非常によく適合するという点には大いに同意する。
RでWITHでデータを準備し、その後にVISUALIZEを付ける構造は、自分のプロットコードともほとんど同じだ。
ただ、単純なDSLであるという利点以外に、もう1つDSLを作るコストを払ってまでggplot2に対する利点が何なのかは、まだよく分からない。
私が可視化のためにggplot2を離れたくなるほぼ唯一の理由は、既存のgeomがある標準的なケースを外れた瞬間に、非標準の可視化をするのがかなり難しいからだ。
少し変わったものを作りたいとき、ggplotに親和的なアダプターを無理に作るより、むしろ下位のprimitive drawingに降りたほうがずっと簡単なことが多かった。
よく使う部分仕様を関数で包むだけでも、
+で合成するのか、|>や昔の%>%のようなパイプでつなぐのかによって、あまり滑らかでないと感じることが多い。そしてggplot2の開発を止めるつもりもまったくない。
ggsqlは、新しいユーザー層に届き、強力な可視化を新しい文脈に置こうとする試みを一部含んだプロジェクトだ。
普段の大半の時間をRで過ごしている人なら、主要なターゲットユーザーではない可能性が高い。
ただ、ggplot2にはないかなり面白い要素もあるので、探ってみる楽しさはあるかもしれないと思う。
|>と%>%は同じ演算子ではない。比較的新しいbase pipeである
|>のほうが速くはあるが、関数の第1引数以外の位置に渡すときに%>%のドットplaceholderのような機能をサポートしていない。そのため場合によっては、
%>%のほうが式を少しきれいにできることもある。これは本当に良いと思う。
私たちもGFQLというgraph dataframe query languageを作る中で、似たような結論に達した。
とくに、コードのsandboxなしでも使えるLLMフレンドリーなインターフェースが、可視化と分析のスタックには必要だった。
基本的なopencypher拡張だけでも、かなり豊かなGPU視覚分析パイプラインを作れることが分かっており、同じ理由でテーブルの世界でSQLへ向かうアプローチも非常に妥当だと思える。
GFQL側の例としては、データ読み込み、shape変換、アルゴリズムによるenrichment、視覚エンコーディング、第一級パイプラインを扱う overall pipelines と、単純な呼び出し形式の declarative visual encodings を参考にするとよい。
かなり良さそうに見える。
ただ、構文サポートがない環境でも自然にdegradeする方法があればよいと思う。
私も似た方向で、ただしGoGよりはずっと単純なSQL内部アプローチを考えたことがあり、そちらはdegrade可能だった。
読みやすい文法ではないが、sqlnb spec のような形だった。
できればもう少し具体的に説明してほしい。
同系統のツールとしては、DuckDBベースのShaperも思い浮かぶ。
ダッシュボード全体をSQLファーストで扱うアプローチで、getting startedドキュメントを見ると方向性が近いと感じる。
まずggsqlは本当にすばらしく見えるし、早く試してみたい。
ただ、ドキュメントで目立って不足している点が1つあり、出力形式の説明を見つけにくかった。
PDFに出力できるのか、SVGやPNGは可能なのか、縦横サイズのような出力制御をどう行うのかが、あまり見えてこなかった。
私が見つけられた最も近い手がかりは、Pythonライブラリのドキュメントにある
chart.display()とchart.save("chart.html")くらいだった。この出力は既存のツールですでにインタラクティブチャート、SVG、PNGなどにレンダリングでき、サイズのような制御もそれらのツールの設定に従うことになる。
ggsql Jupyter kernelは、このvegalite specを使ってQuartoドキュメント内でチャートを出力できる。
今後は、この中間的なvegalite段階を経由しない高性能writerを新たに作る計画なので、その時点ではこうした質問にも、より明確に答えられると思う。
近い将来でも遠い将来でも、ggplot2拡張パッケージ群との統合計画があるのか気になった。
すでに言及されていた話なら申し訳ない。
このプロジェクトの目的はggplot2を置き換えることではなく、別のアプローチを提供することにある。
ggplot2ができることの多くは実現できるだろうし、ggplot2にはできない一部も可能になるかもしれないが、今後も長いあいだ、多くの作業ではggplot2のほうが強力だろうと予想している。
これ、本当に良さそうなので近いうちに使ってみるつもりだ。
自分に強く刺さったのは grammarドキュメント の説明だった。
すでに慣れ親しんだSELECTでデータを選び、
VISUALIZEまたはVISUALISEでテーブルからプロットへ切り替え、その後DRAWでaestheticsをマッピングし、SCALE、FACET、LABELを順に積み上げていく流れが、SQLの構造的な思考様式そのままに続いている点が印象的だった。私はレイヤリングのアプローチが本当に気に入った。
基本的なチャートを超え始めたとき、他のSQL可視化ハイブリッドツールでよく直面する問題を、この方式はうまく解決しているように見えた。