ggsql - uma gramática gráfica para SQL
(opensource.posit.co)- Uma ferramenta de visualização baseada na sintaxe de SQL que combina consulta de dados e composição de gráficos em um único fluxo por meio de cláusulas como
VISUALIZE,DRAW,PLACE,SCALEeLABEL - É possível mapear colunas para atributos visuais e, por meio de uma composição em camadas, construir dentro da mesma estrutura desde gráficos de dispersão, gráficos de barras, histogramas e boxplots até elementos de anotação
- O resultado de uma consulta SQL é passado diretamente como entrada para a visualização, e algumas camadas têm uma estrutura que obtém apenas agregações com a execução de uma única consulta SQL, o que favorece o processamento de grandes volumes de dados
- O projeto é voltado a um executável pequeno e focado, utilizável sem runtime de R ou Python, o que reforça sua adequação para integração com ferramentas de relatórios baseadas em código e assistentes de análise com IA
- A versão atual é uma alpha-release, e já apresenta planos de expansão como writer de alto desempenho, temas, interatividade, language server, formatter e suporte a dados espaciais
Introdução ao ggsql
- ggsql é uma implementação da grammar of graphics baseada na sintaxe de SQL, adicionando recursos estruturados de visualização ao SQL
- Pode ser usado em Quarto, Jupyter notebooks, Positron, VS Code e mais
- Foi projetado para permitir que usuários de SQL escrevam código de visualização de uma forma familiar
- A estrutura declarativa e combinável de cláusulas do SQL também é aplicada à gramática de visualização
- O texto apresenta a motivação e exemplos de uso, desenvolvendo a sintaxe central do ggsql
Exemplo básico
-
Primeiro gráfico
- É possível criar um gráfico de dispersão com o dataset embutido
penguinsVISUALIZE bill_len AS x, bill_dep AS y FROM ggsql:penguinsDRAW point
- Em
VISUALIZE, as colunas de dados são mapeadas para atributos visuais, eDRAW pointcria uma camada de pontos usando esse mapeamento básico - Apenas adicionando
species AS color, já é possível aplicar a distinção por categoria de corVISUALIZE bill_len AS x, bill_dep AS y, species AS color FROM ggsql:penguinsDRAW point
- Ao adicionar
DRAW smooth, é possível sobrepor uma camada de linha de regressão à camada de pontos- O mapeamento de cor por espécie é mantido, criando uma linha separada para cada
species
- O mapeamento de cor por espécie é mantido, criando uma linha separada para cada
- Em vez de tipos de gráfico pré-definidos, o projeto adota uma abordagem de combinação de componentes modulares
- Mantendo a mesma estrutura, é possível mudar para uma visualização completamente diferente
VISUALIZE island AS x, species AS color FROM ggsql:penguinsDRAW bar
- É possível criar um gráfico de dispersão com o dataset embutido
-
Exemplo completo
- A parte superior é uma consulta SQL comum, e a parte após
VISUALIZEé separada como consulta de visualização- No exemplo, é usado o backend DuckDB
- Na parte SQL,
ROW_NUMBER()eQUALIFYsão usados emastronauts.parquetpara manter apenas a missão mais recente de cada nome - Em seguida, dois conjuntos são combinados
year_of_selection - year_of_birthé calculado comoagee recebe a categoriaAge at selectionyear_of_mission - year_of_birthé calculado comoagee recebe a categoriaAge at mission- Os dois resultados são combinados com
UNION ALL
- Na consulta de visualização, são feitos os mapeamentos
age AS xecategory AS fill, e usa-seDRAW histogramSETTING binwidth => 1, position => 'identity'é especificado
PLACE ruleadiciona uma anotação com a posição média pré-calculadax => (34, 44),linetype => 'dotted'
PLACE textadiciona anotação em textox => (34, 44, 60)y => (66, 49, 20)- O rótulo inclui
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)são especificados
SCALE fill TO accentconverte os valores mapeados emfillpara a paleta de coresaccent- A cláusula
LABELcontrola o título, subtítulo, rótulo do eixo x e rótulo da legenda- Título:
How old are astronauts on their most recent mission? - Subtítulo:
Age of astronauts when they were selected and when they were sent on their mission - Eixo x:
Age of astronaut (years) fill => null
- Título:
- A parte superior é uma consulta SQL comum, e a parte após
Estrutura da consulta de visualização
- Antes de
VISUALIZEhá SQL puro, e a tabela resultante não é retornada como tabela, mas passada diretamente como entrada da visualização - Tabelas ou CTEs criadas na parte SQL podem ser referenciadas na consulta de visualização
- Se os dados já estiverem em um formato adequado para visualização, a parte SQL pode ser omitida
VISUALIZE year_of_selection AS x, year_of_mission AS y FROM 'astronauts.parquet'
VISUALIZEouVISUALISEmarca o fim da consulta SQL e o início da consulta de visualização- O mapeamento conecta colunas a atributos visuais, ou seja, aesthetics
- No exemplo,
agecorresponde à posição no eixo x ecategoryà cor de preenchimento
- No exemplo,
DRAWadiciona camadas à visualização- Há tipos simples, como
point, e tipos que exigem cálculo de agregação por intervalos, comohistogram - As camadas são renderizadas na ordem em que são definidas
- Há tipos simples, como
PLACEé uma cláusula irmã deDRAW, dedicada a annotation, usando valores literais em vez de dados tabulares- A visualização do exemplo é composta por três camadas: uma camada de histograma, uma camada de annotation com linha-guia e uma camada de annotation em texto
- Uma camada não corresponde necessariamente a apenas um objeto gráfico, podendo renderizar vários objetos individuais do mesmo tipo
SCALEé a cláusula que converte valores de dados em valores adequados ao aesthetic- Além de transformar categorias textuais em cores reais, também pode realizar transformações contínuas, definir break points e configurar tipos de escala como ordinal ou binned
LABELoferece suporte para adicionar e modificar rótulos de texto, como título, subtítulo, títulos de eixos e títulos de legenda
Dando um passo atrás
- O exemplo acima inclui muita sintaxe, mas cobre de uma vez partes importantes da gramática principal
- Muitas consultas de visualização podem ser muito mais simples do que isso
- É mostrado um exemplo de boxplot do ano de nascimento por gênero usando
astronauts.parquetVISUALIZE sex AS x, year_of_birth AS y FROM 'astronauts.parquet'DRAW boxplot
- O código pode ser mais longo do que em outros sistemas de plotagem, mas oferece características mais estruturadas, combináveis e autoexplicativas
- Essas características facilitam ao usuário internalizar o comportamento de todo tipo de gráfico e também favorecem futuros assistentes de programação com LLM
- A mesma relação pode ser facilmente convertida para um gráfico de dispersão com jitter
DRAW pointSETTING position => 'jitter'
- Também é possível especificar que o jitter siga a distribuição dos dados, dando características de violin plot
SETTING position => 'jitter', distribution => 'density'
- Essa estrutura sintática e essa combinabilidade facilitam o trabalho iterativo em análise exploratória e design de visualização
Por que ggsql
- São apresentados cinco motivos para desenvolver o ggsql
- Apoiar analistas e cientistas de dados que trabalham principalmente com SQL
- A alta compatibilidade entre SQL e grammar of graphics
- Construir uma ferramenta poderosa de visualização baseada em código sem depender de uma linguagem de programação completa como R ou Python
- As fortes capacidades dos LLMs em SQL e a possibilidade de novas interfaces de visualização
- Aplicar em uma nova base os 18 anos de experiência no desenvolvimento do ggplot2
-
Olá, usuário de SQL
- Mesmo enquanto R e Python ganharam destaque durante a revolução da ciência de dados, o SQL continuou sendo uma base confiável para o trabalho com dados
- Há muitos profissionais de dados que usam apenas SQL ou principalmente SQL
- Para eles, as opções de visualização disponíveis até agora são consideradas, no geral, pouco ideais
- Exportar os dados para usar R ou Python
- Usar ferramentas de BI com GUI que oferecem pouco suporte à reprodutibilidade
- Usar ferramentas de visualização embutidas na própria consulta, mas consideradas insuficientemente poderosas ou ergonômicas
- A sintaxe do ggsql foi projetada para que usuários de SQL a entendam de imediato
- Aproveitando a expectativa por cláusulas declarativas e combináveis
- O ggsql não apenas melhora a forma de visualizar dados, mas também ajuda a atrair usuários de SQL para o ecossistema de criação e compartilhamento de relatórios baseados em código com Quarto
-
Transformação declarativa de dados, visualização declarativa
- SQL é uma linguagem específica de domínio para lidar com dados relacionais armazenados em uma ou mais tabelas
- A sintaxe de SQL se baseia em conceitos de álgebra relacional e oferece uma maneira estrutural de pensar a manipulação de dados
- A semântica de SQL define um conjunto modular de operações declarativas, e não funcionais
- A grammar of graphics é uma estrutura teórica que decompõe o conceito de visualização de dados em componentes modulares
- Ferramentas como ggplot2 levam esse conceito à implementação prática
- A grammar of graphics também define um conjunto modular de operações declarativas, e não funcionais
- Os dois sistemas têm grande semelhança na forma como abordam seus respectivos domínios, o que permite montar um pipeline completo natural e poderoso, dos dados brutos até a visualização final
-
No runtime, no problem
- ggplot2 exige instalação de R, e plotnine exige instalação de Python
- Em contraste, há vantagens claras em uma ferramenta de visualização baseada em um executável único e focado
- É mais fácil embutir um pequeno executável em outras ferramentas do que empacotar R/Python ou exigir sua instalação
- Como o escopo é menor, também é mais fácil limitar em sandbox execuções de código malicioso ou acidental
- Essas características tornam o ggsql uma opção mais atraente para integração com assistentes de análise com IA ou ferramentas de relatórios baseadas em código que executam código em vários ambientes
- Sair de uma linguagem interpretada traz limitações, mas também ganhos
- A vantagem mais importante é que, graças à estrutura rígida, o backend pode executar todo o pipeline de dados por camada em uma única consulta SQL
- Por exemplo, ao criar um bar plot com 10 bilhões de registros de transações, o data warehouse traz apenas os valores de contagem de cada barra, e não as 10 bilhões de linhas completas
- O mesmo princípio se aplica a tipos de camada mais complexos, como boxplot e density plot
- Isso contrasta com a maioria das ferramentas de visualização, que primeiro materializam todo o conjunto de dados para depois calcular e plotar
-
SELECT pod_door FROM bay WHERE closed- Já foi demonstrado que os LLMs são muito eficazes em converter linguagem natural em SQL
- A expectativa é que o mesmo nível de eficácia possa ser aplicado ao ggsql
- Em
querychat, já é possível fazer exploração visual de dados em linguagem natural por meio do ggsql - Como o ggsql oferece um runtime mais seguro e leve que R ou Python, ele inspira mais confiança na implantação de agentes de programação em ambientes de produção
-
We are now wise beyond our years
- Os 18 anos de desenvolvimento e manutenção do ggplot2 representam 18 anos de reflexão acumulada sobre gramática de visualização, usabilidade e design
- Nem todo esse conhecimento pode ser reinserido no ggplot2
- É preciso respeitar decisões tomadas há muito tempo e as expectativas dos usuários, e mesmo mudanças mais ousadas só podem ocorrer de forma muito gradual
- ggsql é uma blank slate
- Um projeto construído do zero
- Um sistema projetado para um ambiente sem expectativas prévias sobre ferramentas de visualização
- O texto afirma que esse ponto de partida trouxe liberdade e energia ao processo de desenvolvimento, algo que também aparece na experiência de uso
Futuro
- A versão atual é uma alpha-release e ainda não está concluída
- É apresentada uma lista não exaustiva do que se pretende adicionar no futuro
- Um novo writer de alto desempenho escrito em Rust do zero
- Infraestrutura de temas
- Interatividade
- Fluxo de implantação de ponta a ponta, do Posit Workbench ou Positron até o Connect
- Um language server completo para ggsql e um formatter de código
- Suporte a dados espaciais
-
O que isso significa para o desenvolvimento do ggplot2
- É mencionado que usuários do ggplot2 podem olhar para o anúncio do ggsql com uma mistura de receio e expectativa
- A resposta para a pergunta sobre a Posit deixar o ggplot2 de lado para focar no ggsql é não
- O ggplot2 já é muito maduro e estável, mas o plano é continuar dando suporte e expandindo-o
- Há a expectativa de que o processo de desenvolvimento do ggsql também contribua para levar novos recursos ao ggplot2
Saiba mais
- Quem quiser começar a usar o ggsql imediatamente pode consultar as instruções de instalação e o tutorial na seção Getting started do site do ggsql
- Na página de documentação, é possível ver todos os recursos atualmente suportados pelo ggsql
- O texto também menciona que feedback sobre a experiência de uso será muito bem-vindo
1 comentários
Comentários do Hacker News
Posso ter entendido assim por ter passado o texto rápido demais, mas só pelo post do blog e pela documentação senti que a relação com bancos de dados SQL não estava explicada com clareza
No começo, imaginei que fosse algo como uma DSL de visualização parecida com SQL processada por uma biblioteca de gráficos no frontend
A documentação anatomy parecia indicar isso, mas no FAQ, em "Can I use SQL queries inside the VISUALISE clause", dizia que parte da sintaxe é enviada diretamente ao banco de dados
Na página inicial está escrito "ggsql interfaces directly with your database", mas não ficou muito claro como essa conexão acontece de fato, então achei um pouco confuso
O ggsql pode se conectar diretamente a um backend de banco de dados e, se você quiser, também pode rodar com DuckDB em memória
As consultas de visualização são convertidas em consultas SQL para cada camada da visualização, e as tabelas resultantes são usadas na renderização
Por exemplo, uma consulta como
VISUALISE page_views AS x FROM visits DRAW smoothé transformada em SQL que calcula um smoothing kernel sobre os dados, e com os pontos retornados é desenhado o gráfico de linha finalO reader cuida da conexão com o banco e da geração do dialeto SQL adequado para cada DB
No estágio alpha atual, ele suporta duckdb, sqlite e um reader ODBC experimental, e o desenvolvimento está focado principalmente em DuckDB local baseado em arquivo
A ideia central é converter a consulta de visualização em várias consultas SQL, executá-las no banco e montar o gráfico usando apenas os pequenos resultados retornados
Assim, mesmo com muitas linhas, é possível calcular em SQL apenas as estatísticas necessárias para um histograma e trazer só alguns pontos necessários para desenhar a altura das barras
O padrão é uma conexão DuckDB em memória, e no CLI é possível conectar a um arquivo em disco ou a um URI ODBC com
--readerNo Positron, isso pode ser configurado mais facilmente pelo painel "Connections", e no kernel Jupyter do ggsql é possível definir o reader com um magic SQL comment
Também pretendemos reforçar melhor na documentação essa explicação sobre integração com ferramentas externas
SQL é uma linguagem declarativa de manipulação de dados, muito usada para consultar bancos de dados, mas não está presa apenas a bancos
Dá para aplicar SQL a arquivos planos, fluxos de dados e dados na memória de um programa
E, por outro lado, também é possível consultar um banco de dados sem SQL
Enquanto eu passava pelo texto, tentei entender por que isso seria necessário e qual problema resolve, mas isso não ficou muito claro para mim
Parecia talvez uma forma de visualizar diretamente tabelas de um banco SQL remoto, evitando a etapa de primeiro trazer tudo para um data frame em R e só então rodar ggplot
Mas aí fiquei me perguntando por que seria necessário criar uma nova linguagem parecida com SQL
Já existe o dbplyr em R, que traduz entre R e SQL, então talvez fosse mais direto expandir o ggplot para suportar objetos tbl do dbplyr e gerar SQL diretamente
Ou talvez a ideia seja que SQL já é uma linguagem tão familiar que muita gente gostaria de fazer tarefas no estilo ggplot usando essa sintaxe
Só depois de ler quase toda a documentação entendi que isso é um app de visualização independente com backends DuckDB e SQLite, que hoje renderiza com Vegalite e pretende adicionar mais backends e renderizadores no futuro
Como diz um comentário abaixo, parece uma ferramenta voltada a usuários centrados em SQL que não conhecem Python nem R
Concordo, porém, que o texto de apresentação poderia ter explicado isso melhor
Na minha experiência, a linguagem comum compartilhada por analistas, cientistas e engenheiros muitas vezes acaba sendo SQL
Dá para fazer a mesma coisa em R, mas na prática os projetos nem sempre são escritos em R ou Python, enquanto bancos SQL e mecanismos de acesso normalmente já existem
Além disso, eu uso com frequência células SQL em notebooks marimo com DuckDB rodando em background, e poder plotar direto a partir de SQL ali seria muito conveniente
Por fim, sempre achei as APIs de plotting em Python relativamente difíceis de memorizar e dominar
Mesmo para desenhar um scatterplot simples com matplotlib, existe boilerplate demais, então ter uma sintaxe unificada dentro da mesma linguagem de consulta me parece bem interessante
O ponto interessante está nessa combinação entre SQL como interface e a formalidade da GoG, mais do que em uma biblioteca específica
O renderizador ou runtime real é importante, claro, mas me parece mais um detalhe de implementação
Claro, não é algo impossível de fazer com número parecido de linhas em R, Python ou matplotlib
Mas fazer sandboxing seguro desses ambientes contra entradas maliciosas é difícil, e uma linguagem declarativa assim torna muito mais fácil hospedar algo em que usuários não confiáveis mandem ggsql e o sistema apenas gere gráficos
Nesse sentido, há utilidade clara
Ainda assim, na maioria dos usos comuns, talvez seja mais fácil pedir ao seu LLM favorito para gerar código matplotlib
Torço pelo projeto e concordo bastante que o conceito se encaixa muito bem no SQL
Em R, preparar os dados com WITH e depois acrescentar VISUALIZE é quase idêntico à forma como eu mesmo escrevo código de plotting
Mas, tirando a vantagem de ser uma DSL simples, ainda não está claro para mim qual é a vantagem em relação ao ggplot2 que justificaria o custo de criar mais uma DSL
Quase o único motivo pelo qual eu abandonaria o ggplot2 por causa de visualização é que, quando se sai dos casos padrão em que já existe um geom pronto, fazer visualizações não padrão se torna bem difícil
Quando eu quero criar algo um pouco diferente, muitas vezes é muito mais fácil descer para primitivas de desenho de nível mais baixo do que tentar forçar um adaptador amigável ao ggplot
Até mesmo encapsular especificações parciais comuns em funções nem sempre flui bem, dependendo de se a composição é feita com
+ou encadeada com|>ou o antigo%>%E também não temos nenhum plano de parar o desenvolvimento do ggplot2
O ggsql é, em parte, uma tentativa de alcançar um novo público e colocar visualizações poderosas em novos contextos
Se você passa a maior parte do tempo em R, provavelmente não é o usuário-alvo principal
Ainda assim, ele tem alguns elementos bem interessantes que o ggplot2 não tem, então pode haver valor em explorá-lo
|>e%>%não são o mesmo operadorO
|>é o pipe base relativamente recente e é mais rápido, mas não oferece recursos como o placeholder com ponto do%>%para passar argumentos em posições diferentes da primeiraPor isso, em certos casos,
%>%ainda pode deixar a expressão um pouco mais limpaIsso parece realmente muito bom
Nós também chegamos a uma conclusão parecida ao criar a GFQL, uma graph dataframe query language
Em especial, precisávamos de uma interface amigável para LLMs que pudesse ser usada na pilha de visualização e análise sem exigir sandbox de código
Descobrimos que mesmo apenas com extensões básicas de opencypher já dá para construir pipelines bem ricos de análise visual em GPU, então pelo mesmo motivo a ideia de seguir para SQL no mundo tabular também parece muito válida
Como exemplos do lado da GFQL, vale olhar overall pipelines, que cobre carregamento de dados, transformação de shape, enrichment baseado em algoritmos, codificação visual e pipelines de primeira classe, além de declarative visual encodings em uma forma de chamada simples
Isso parece bem legal
Só gostaria que houvesse uma forma de degradar com elegância em ambientes sem suporte à sintaxe
Eu mesmo já pensei em uma abordagem parecida, mas muito mais simples e dentro do SQL, não da GoG, e ali era possível degradar
Não era uma sintaxe bonita de ler, mas era algo mais na linha da spec do sqlnb
Se puder, seria bom explicar isso de forma mais concreta
Outra ferramenta nessa mesma linha que me veio à cabeça foi o Shaper, baseado em DuckDB
A proposta é tratar dashboards inteiros com uma abordagem SQL-first, e a documentação de getting started passa uma direção parecida
Em primeiro lugar, o ggsql parece realmente incrível e estou ansioso para testar
Mas senti falta de uma coisa visível na documentação: foi difícil encontrar explicação sobre os formatos de saída
Não ficou claro se dá para exportar em PDF, se há suporte a SVG ou PNG, nem como controlar tamanho de largura e altura na saída
A pista mais próxima que encontrei foi
chart.display()echart.save("chart.html")na documentação da biblioteca PythonEssa saída pode ser renderizada como gráficos interativos, SVG, PNG e outros formatos com ferramentas já existentes, e controles como tamanho seguem as configurações dessas ferramentas
O kernel Jupyter do ggsql usa esse spec do vegalite para exibir gráficos dentro de documentos Quarto
No futuro, planejamos criar um writer de alto desempenho que não passe por essa etapa intermediária do vegalite, e aí provavelmente conseguiremos dar respostas mais claras para esse tipo de pergunta
Fiquei curioso se existe algum plano de integração com os pacotes de extensão do ggplot2, seja no futuro próximo ou distante
Se isso já tiver sido mencionado, peço desculpas
O objetivo deste projeto não é substituir o ggplot2, mas oferecer uma abordagem diferente
Ele conseguirá fazer muitas das coisas que o ggplot2 faz, e talvez algumas que o ggplot2 não faz, mas imagino que por muito tempo o ggplot2 ainda será mais poderoso em muitas tarefas
Isso parece realmente muito legal e pretendo testar em breve
O que mais me chamou atenção foi a explicação na documentação da grammar
A ideia de selecionar dados com o já familiar SELECT, depois passar da tabela para o gráfico com
VISUALIZEouVISUALISE, mapear aesthetics comDRAWe então ir acumulandoSCALE,FACETeLABELem sequência segue exatamente a forma estruturada de pensar do SQLEu gostei muito da abordagem em camadas
Quando você começa a ir além do gráfico básico, isso parece resolver bem um problema que eu via com frequência em outras ferramentas híbridas de visualização com SQL