ggsql - una gramática gráfica para SQL
(opensource.posit.co)- Herramienta de visualización basada en sintaxis SQL que combina en un mismo flujo la consulta de datos y la construcción de gráficos mediante cláusulas como
VISUALIZE,DRAW,PLACE,SCALEyLABEL - Permite mapear columnas a propiedades visuales y, con un enfoque de composición por capas, construir dentro de una misma estructura diagramas de dispersión, gráficos de barras, histogramas, boxplots e incluso elementos de anotación
- Los resultados de consultas SQL se pasan directamente como entrada de visualización, y algunas capas tienen una estructura que obtiene solo las agregaciones mediante la ejecución de una sola consulta SQL, lo que resulta ventajoso para procesar grandes volúmenes de datos
- Diseñado con la idea de un ejecutable pequeño y enfocado que puede usarse sin runtime de R o Python, lo que también resalta su idoneidad para integrarse en herramientas de reportes basadas en código y asistentes de análisis con IA
- La versión actual es una alpha-release, y se presentan planes de expansión como writer de alto rendimiento, temas, interactividad, language server, formatter y soporte para datos espaciales
Introducción a ggsql
- ggsql es una implementación de grammar of graphics basada en sintaxis SQL que añade capacidades de visualización estructuradas a SQL
- Puede usarse en Quarto, Jupyter notebooks, Positron, VS Code y más
- Está diseñado para que los usuarios de SQL puedan escribir código de visualización de una forma familiar
- Aplica a la gramática de visualización la estructura declarativa y componible de cláusulas propia de SQL
- Presenta la motivación y ejemplos de uso, desarrollando la sintaxis central de ggsql
Ejemplos básicos
-
Primer gráfico
- Se puede crear un diagrama de dispersión con el dataset integrado
penguinsVISUALIZE bill_len AS x, bill_dep AS y FROM ggsql:penguinsDRAW point
- En
VISUALIZE, las columnas de datos se mapean a propiedades visuales, yDRAW pointcrea una capa de puntos usando ese mapeo base - Con solo añadir
species AS color, se puede aplicar una distinción por categorías de colorVISUALIZE bill_len AS x, bill_dep AS y, species AS color FROM ggsql:penguinsDRAW point
- Al añadir
DRAW smooth, se puede apilar una capa de línea de regresión sobre la capa de puntos- Se mantiene el mapeo de color por especie, por lo que se genera una línea separada para cada
species
- Se mantiene el mapeo de color por especie, por lo que se genera una línea separada para cada
- En lugar de adoptar tipos de gráficos predefinidos, usa un enfoque de combinación de componentes modulares
- Manteniendo la misma estructura, es posible cambiar a una visualización completamente distinta
VISUALIZE island AS x, species AS color FROM ggsql:penguinsDRAW bar
- Se puede crear un diagrama de dispersión con el dataset integrado
-
Ejemplo completo
- La parte superior se distingue como una consulta SQL común, y después de
VISUALIZEcomienza la consulta de visualización- En el ejemplo se usa un backend de DuckDB
- La parte SQL usa
ROW_NUMBER()yQUALIFYpara conservar solo la misión más reciente por nombre a partir deastronauts.parquet - Luego se combinan dos conjuntos
- Se calcula
year_of_selection - year_of_birthcomoagey se asigna la categoríaAge at selection - Se calcula
year_of_mission - year_of_birthcomoagey se asigna la categoríaAge at mission - Ambos resultados se combinan con
UNION ALL
- Se calcula
- En la consulta de visualización se mapean
age AS xycategory AS fill, y luego se usaDRAW histogram- Se especifica
SETTING binwidth => 1, position => 'identity'
- Se especifica
PLACE ruleañade una anotación en la posición media calculada previamentex => (34, 44),linetype => 'dotted'
PLACE textañade anotaciones de textox => (34, 44, 60)y => (66, 49, 20)- La etiqueta incluye
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! - Se especifican
hjust => 'left',vjust => 'top',offset => (10, 0)
SCALE fill TO accentconvierte los valores mapeados defilla la paleta de coloraccent- La cláusula
LABELcontrola el título, subtítulo, etiqueta del eje x y la etiqueta de la leyenda- 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 - Eje x:
Age of astronaut (years) fill => null
- Título:
- La parte superior se distingue como una consulta SQL común, y después de
Estructura de la consulta de visualización
- Antes de
VISUALIZEhay SQL puro, y la tabla resultante no se devuelve como tabla, sino que se pasa directamente como entrada a la visualización - Las tablas o CTE creadas en la parte SQL pueden referenciarse en la consulta de visualización
- Si los datos ya están en una forma adecuada para visualizarse, la parte SQL puede omitirse
VISUALIZE year_of_selection AS x, year_of_mission AS y FROM 'astronauts.parquet'
VISUALIZEoVISUALISEmarca el final de la consulta SQL y el comienzo de la consulta de visualización- El mapeo cumple la función de conectar columnas con propiedades visuales, es decir, aesthetics
- En el ejemplo,
agecorresponde a la posición en el eje x ycategoryal color de relleno
- En el ejemplo,
DRAWañade capas a la visualización- Hay tipos simples como
pointy otros comohistogram, que requieren calcular agregaciones por intervalos - Las capas se renderizan en el orden en que se definen
- Hay tipos simples como
PLACEes una cláusula hermana deDRAWdedicada exclusivamente a annotation, usando valores literales en lugar de datos tabulares- La visualización del ejemplo consta de tres capas: una capa de histograma, una capa de anotación de línea guía y una capa de anotación de texto
- Una capa no necesariamente corresponde a un único objeto gráfico, y puede renderizar varios objetos individuales del mismo tipo
SCALEes la cláusula que transforma valores de datos en valores adecuados para un aesthetic- Además de convertir categorías de texto en colores reales, también puede realizar transformaciones continuas, definir break points y establecer tipos de escala como ordinal o binned
LABELpermite añadir y modificar etiquetas de texto como título, subtítulo, títulos de ejes y títulos de leyenda
Dando un paso atrás
- El ejemplo anterior incluye mucha sintaxis, pero cubre de una vez partes importantes del núcleo del lenguaje
- Muchas consultas de visualización pueden ser mucho más simples que eso
- Se presenta un ejemplo de boxplot del año de nacimiento por género usando
astronauts.parquetVISUALIZE sex AS x, year_of_birth AS y FROM 'astronauts.parquet'DRAW boxplot
- El código puede ser más largo que en otros sistemas de gráficos, pero ofrece propiedades más estructuradas, componibles y autoexplicativas
- Estas propiedades facilitan que los usuarios interioricen el comportamiento de todo tipo de gráficos, y también benefician a futuros asistentes de codificación basados en LLM
- La misma relación puede convertirse fácilmente en un diagrama de dispersión con jitter
DRAW pointSETTING position => 'jitter'
- También se puede hacer que el jitter siga la distribución de los datos para darle carácter de violin plot
SETTING position => 'jitter', distribution => 'density'
- Esta estructura sintáctica y capacidad de composición facilitan el trabajo repetitivo en el análisis exploratorio y el diseño de visualizaciones
¿Por qué ggsql?
- Se presentan cinco razones para desarrollar ggsql
- Apoyar a analistas y científicos de datos que trabajan principalmente con SQL
- La alta afinidad entre SQL y grammar of graphics
- Construir una herramienta potente de visualización basada en código sin depender de un lenguaje de programación completo como R o Python
- Las grandes capacidades de los LLM para procesar SQL y las nuevas posibilidades de interfaces de visualización
- Aplicar 18 años de experiencia desarrollando ggplot2 sobre una nueva base
-
Hello, SQL user
- Aunque durante la revolución de la ciencia de datos R y Python recibieron gran atención, SQL ha seguido siendo una base confiable para trabajar con datos
- Existe una gran cantidad de personas que trabajan con datos usando solo SQL o principalmente SQL
- Para ellas, las opciones de visualización existentes mencionadas en el texto son en general poco óptimas
- Exportar los datos para usar R o Python
- Usar herramientas BI basadas en GUI con escaso soporte para reproducibilidad
- Usar herramientas de visualización integradas en la propia consulta, pero consideradas insuficientemente potentes o ergonómicas
- La sintaxis de ggsql está diseñada para que los usuarios de SQL la entiendan de inmediato
- Aprovecha la expectativa de cláusulas declarativas y componibles
- ggsql no solo mejora la forma de visualizar, sino que también sirve para incorporar a los usuarios de SQL al ecosistema de creación y compartición de reportes basados en código con Quarto
-
Transformación declarativa de datos, visualización declarativa
- SQL es un lenguaje específico de dominio para tratar datos relacionales almacenados en una o más tablas
- La sintaxis de SQL se basa en conceptos de álgebra relacional y ofrece una forma de pensar estructuralmente la manipulación de datos
- La semántica de SQL no es funcional, sino que define un conjunto declarativo de operaciones modulares
- La grammar of graphics es un marco teórico que descompone el concepto de visualización de datos en componentes modulares
- Herramientas como ggplot2 llevan ese concepto a una implementación práctica
- La grammar of graphics también define un conjunto declarativo de operaciones modulares más que funcionales
- Ambos sistemas comparten mucho en la forma en que abordan sus respectivos dominios, y permiten construir un pipeline integral natural y potente desde los datos en bruto hasta la visualización final
-
No runtime, no problem
- ggplot2 requiere una instalación de R, y plotnine requiere una instalación de Python
- En cambio, una herramienta de visualización basada en un ejecutable único y enfocado tiene ventajas claras
- Es más fácil integrar un ejecutable pequeño dentro de otras herramientas que empaquetar R/Python o exigir su instalación
- Al tener un alcance reducido, es más sencillo limitar con sandbox la ejecución de código malicioso o accidental
- Estas características hacen de ggsql una opción más atractiva para integrarse en asistentes de análisis con IA o herramientas de reportes basadas en código que ejecutan código en múltiples entornos
- Salirse de un lenguaje interpretado también implica limitaciones, pero hay mucho que se gana
- La ventaja más importante es que, gracias a su estructura estricta, el backend puede ejecutar por capa todo el pipeline de datos como una única consulta SQL
- Por ejemplo, al crear un bar plot con 10 mil millones de transacciones, desde el data warehouse solo se obtienen los valores de conteo de cada barra, sin traer las 10 mil millones de filas completas
- El mismo principio se aplica a tipos de capas más complejos como boxplot o density plot
- Esta es una característica que contrasta con la mayoría de las herramientas de visualización, que primero materializan todos los datos y luego calculan y grafican
-
SELECT pod_door FROM bay WHERE closed- Está demostrado que los LLM son muy eficaces para convertir lenguaje natural en SQL
- Se plantea la expectativa de que el mismo nivel de eficacia pueda aplicarse a ggsql
- En
querychat, ya es posible la exploración visual de datos en lenguaje natural mediante ggsql - Como ggsql tiene un runtime más seguro y ligero que R o Python, ofrece mayor confianza al desplegar agentes de código en entornos de producción
-
We are now wise beyond our years
- Los 18 años de desarrollo y mantenimiento de ggplot2 representan 18 años de reflexión acumulada sobre gramáticas de visualización, usabilidad y diseño
- No todo ese conocimiento puede volver a incorporarse a ggplot2
- Hay que respetar decisiones tomadas hace mucho tiempo y las expectativas de los usuarios, y aun cuando se desafían, solo puede hacerse de forma muy gradual
- ggsql es una blank slate
- Un proyecto construido desde cero
- Un sistema diseñado para entornos sin expectativas previas sobre herramientas de visualización
- Se afirma que ese punto de partida dio una sensación de libertad y energía durante el desarrollo, y que eso también se refleja en la experiencia del usuario
Futuro
- La versión actual es una alpha-release y todavía no está terminada
- Se presenta una lista no exhaustiva de lo que se quiere añadir en adelante
- Un nuevo writer de alto rendimiento escrito desde cero en Rust
- Infraestructura de temas
- Interactividad
- Flujo de despliegue de extremo a extremo desde Posit Workbench o Positron hasta Connect
- Un language server completo de ggsql y formatter de código
- Soporte para datos espaciales
-
¿Qué significa para el desarrollo de ggplot2?
- Se menciona que los usuarios de ggplot2 podrían ver el anuncio de ggsql con una mezcla de temor y expectativa
- A la pregunta de si Posit dejará de lado ggplot2 para concentrarse en ggsql, la respuesta es no
- ggplot2 ya es muy maduro y estable, pero se planea seguir dándole soporte y expandiéndolo
- Se espera que el proceso de desarrollo de ggsql también contribuya a aportar nuevas funcionalidades a ggplot2
Más información
- Si quieres empezar a usar ggsql de inmediato, en la sección Getting started del sitio web de ggsql puedes consultar la guía de instalación y el tutorial
- En la página de documentación puedes ver todas las funcionalidades que soporta ggsql
- También se menciona que esperan recibir comentarios sobre la experiencia de uso
1 comentarios
Comentarios en Hacker News
Puede que haya sido porque le di una lectura rápida al texto, pero solo con la entrada del blog y la documentación sentí que la relación con las bases de datos SQL no quedaba explicada con claridad
Al principio supuse que era algo así como una DSL de visualización parecida a SQL que procesaba una librería de gráficos frontend
El documento de anatomy se leía de esa forma, pero en el FAQ de "Can I use SQL queries inside the VISUALISE clause" decía que parte de la sintaxis se envía directamente a la base de datos
En la página principal dice "ggsql interfaces directly with your database", pero no quedaba claro cómo se conecta realmente, y eso me confundió
ggsql puede conectarse directamente al backend de base de datos y, si se quiere, también puede ejecutarse sobre DuckDB en memoria
Las consultas de visualización se convierten en consultas SQL para cada capa de la visualización, y luego esas tablas resultantes se usan para renderizar
Por ejemplo, una consulta como
VISUALISE page_views AS x FROM visits DRAW smoothse transforma en SQL que calcula un kernel de smoothing sobre los datos, y con los puntos devueltos se dibuja el gráfico de líneas finalEl reader se encarga de la conexión a la base de datos y de generar el dialecto SQL adecuado para cada DB
En esta etapa alpha, por ahora soporta duckdb, sqlite y un reader ODBC experimental, y el desarrollo se está haciendo principalmente en torno a DuckDB local basado en archivos
La idea central es convertir una consulta de visualización en varias consultas SQL, ejecutarlas en la base de datos y construir el gráfico solo con la pequeña cantidad de resultados que regresan
Así, incluso si hay muchísimas filas, puede calcular en SQL solo las estadísticas necesarias para un histograma y traer únicamente unos pocos puntos necesarios para dibujar la altura de las barras
El valor predeterminado es una conexión DuckDB en memoria, y en el CLI se puede conectar a un archivo en disco o a un URI ODBC con
--readerEn Positron se puede configurar más fácilmente desde el panel de "Connections", y en el kernel de Jupyter de ggsql se puede especificar el reader con un magic SQL comment
También planean reforzar en la documentación la explicación de este tipo de integración con herramientas externas
SQL es un lenguaje declarativo de manipulación de datos; se usa con frecuencia para consultar bases de datos, pero no está atado exclusivamente a ellas
SQL también puede aplicarse a archivos planos, flujos de datos o datos en la memoria de un programa
Y a la inversa, también es posible consultar una base de datos sin usar SQL
Mientras iba leyendo el texto, trataba de encontrar por qué esto era necesario y qué problema resolvía, pero no terminé de captarlo
Pensé que quizá buscaba visualizar directamente tablas de una base de datos SQL remota y evitar el paso de traerlas primero a un data frame de R para luego correr ggplot
Pero entonces también me pregunté por qué había que crear un nuevo lenguaje tipo SQL
En R ya existe dbplyr, que traduce entre R y SQL, así que me parecía más directo extender ggplot para que soportara objetos tbl de dbplyr y generara SQL directamente
O quizá la idea es que SQL ya es un lenguaje tan familiar que mucha gente querría hacer tareas estilo ggplot con esta sintaxis
Recién después de leer casi toda la documentación entendí que esto es una app de visualización independiente con backends DuckDB y SQLite, que hoy renderiza con Vegalite y que más adelante planea sumar más backends y renderers
Como dice un comentario más abajo, parece una herramienta para que usuarios centrados en SQL puedan crear visualizaciones sin saber Python ni R
Claro, coincido en que habría sido mejor si la presentación lo hubiera explicado un poco más claramente
En mi experiencia, el lenguaje común que comparten analistas, científicos e ingenieros muchas veces termina siendo SQL
En R también se puede hacer lo mismo, pero en los proyectos reales no siempre se trabaja en R o Python; en cambio, casi siempre ya existen una base de datos SQL y un motor de acceso
Además, yo uso con frecuencia celdas SQL en marimo notebook con DuckDB en segundo plano, y ahí sería muy cómodo poder graficar directamente en SQL
Por último, siempre me ha parecido que las API de gráficos en Python son difíciles de memorizar y dominar
Incluso para dibujar un scatterplot simple con matplotlib hay demasiado boilerplate, así que tener una sintaxis unificada dentro del mismo lenguaje de consultas me parece bastante atractivo
Lo interesante está en la combinación de SQL como interfaz con la formalidad de GoG, más que en una librería específica
El renderer o el runtime importan, claro, pero me parecen más bien detalles de implementación
Por supuesto, no es algo imposible de hacer con una cantidad parecida de código en R o Python con matplotlib
Pero hacer sandboxing de esos entornos de forma segura ante entradas maliciosas es difícil, y con un lenguaje declarativo como este sería más fácil alojar un servicio donde usuarios no confiables ingresen ggsql y solo se genere el gráfico
En ese sentido sí tiene utilidad
Aunque para la mayoría de los usos comunes, quizá sea más fácil pedirle a tu LLM favorito que te genere código de matplotlib
Apoyo el proyecto en sí, y coincido bastante en que el concepto encaja muy bien con SQL
En R, preparar datos con WITH y luego agregar VISUALIZE se parece bastante a cómo ya escribo mi código de gráficos
Pero más allá de la ventaja de ser una DSL simple, todavía no tengo claro cuál sería la ventaja frente a ggplot2 que justifique el costo de crear otra DSL
Casi la única razón por la que dejaría ggplot2 por temas de visualización es que, en cuanto uno se sale de los casos estándar donde ya existe un geom, se vuelve bastante difícil hacer visualizaciones no estándar
Cuando quiero construir algo un poco distinto, muchas veces me resulta mucho más fácil bajar a drawing primitives de nivel inferior que tratar de forzar un adaptador amigable con ggplot
Incluso envolver especificaciones parciales comunes dentro de funciones no siempre se siente fluido, según si se componen con
+o si se encadenan con pipes como|>o el viejo%>%Y tampoco tenemos ningún plan de dejar de desarrollar ggplot2
ggsql es, en parte, un proyecto para llegar a nuevos tipos de usuarios y llevar visualizaciones potentes a nuevos contextos
Si alguien pasa la mayor parte de su tiempo en R, probablemente no sea el usuario objetivo principal
Aun así, sí hay algunos elementos bastante interesantes que no están en ggplot2, así que puede ser entretenido explorarlo
|>y%>%no son el mismo operadorEl pipe base relativamente reciente,
|>, es más rápido, pero no admite funciones como el placeholder con punto de%>%para pasar argumentos a posiciones distintas de la primeraPor eso, en algunos casos,
%>%puede hacer que una expresión quede un poco más limpiaEsto me parece realmente bueno
Nosotros también llegamos a conclusiones parecidas al crear GFQL, un graph dataframe query language
En particular, necesitábamos una interfaz amigable para LLM que pudiera usarse en stacks de visualización y análisis sin sandbox de código
Confirmamos que incluso con extensiones básicas de opencypher se puede construir un pipeline bastante rico de análisis visual sobre GPU, y por la misma razón el enfoque de ir hacia SQL en el mundo tabular también me parece totalmente razonable
Como ejemplos del lado de GFQL, vale la pena revisar overall pipelines, que cubre carga de datos, transformación de shape, enrichment basado en algoritmos, visual encoding y pipelines de primera clase, así como declarative visual encodings, con un estilo de llamada más simple
Esto se ve bastante bien
Pero me gustaría que hubiera una forma de que degradara con elegancia incluso en entornos sin soporte para esa sintaxis
Yo también ideé un enfoque parecido, aunque mucho más simple que GoG, para usar dentro de SQL, y ese sí podía degradarse
No era una sintaxis muy agradable de leer, pero era algo como la spec de sqlnb
Si es posible, estaría bien que lo explicaras un poco más en concreto
Otra herramienta en una línea parecida que me viene a la mente es Shaper, basado en DuckDB
Su enfoque también es manejar dashboards completos con una lógica SQL-first, y al ver la documentación de getting started me dio la impresión de que va por un rumbo similar
Antes que nada, ggsql se ve realmente genial y tengo ganas de probarlo pronto
Pero sí noté algo que parecía faltar en la documentación: costaba encontrar una explicación de los formatos de salida
No quedaba claro si puede exportar a PDF, si soporta SVG o PNG, o cómo se controlan cosas como el tamaño horizontal y vertical de salida
La pista más cercana que encontré fue
chart.display()ychart.save("chart.html")en la documentación de la librería de PythonEsa salida ya puede renderizarse como gráfico interactivo, SVG, PNG y demás con herramientas existentes, y controles como el tamaño se manejan siguiendo la configuración de esas herramientas
El kernel de Jupyter de ggsql puede usar este vegalite spec para mostrar gráficos dentro de documentos Quarto
Más adelante planean crear un writer de alto rendimiento que no pase por esta etapa intermedia de vegalite, así que en ese momento probablemente puedan dar una respuesta más clara a este tipo de preguntas
Me preguntaba si hay planes de integración con los paquetes de extensión de ggplot2 en el futuro cercano o lejano
Si ya lo mencionaron antes, disculpas
El objetivo de este proyecto no es reemplazar ggplot2, sino ofrecer un enfoque distinto
Puede hacer muchas de las cosas que hace ggplot2, e incluso algunas que ggplot2 no puede, pero creo que durante mucho tiempo ggplot2 seguirá siendo más potente para muchas tareas
Esto se ve realmente genial y pienso probarlo pronto
Lo que más me hizo clic fue la explicación en el documento de grammar
Me impresionó cómo el flujo conserva exactamente la forma estructurada de pensar de SQL: eliges datos con el ya familiar SELECT, cambias de tabla a gráfico con
VISUALIZEoVISUALISE, luego mapeas aesthetics conDRAW, y después vas apilandoSCALE,FACETyLABELA mí me encantó de verdad el enfoque por capas
Me dio la impresión de que resuelve muy bien problemas que suelen aparecer en otras herramientas híbridas de visualización en SQL cuando uno empieza a ir más allá de los gráficos básicos