CommunityProgramación y desarrollogithub.com

pwquint24/org-babel-polyglot

Guía para construir pipelines de análisis de datos multilingüe, paso de variables entre bloques, fórmulas de tabla con org-sbe y llamadas remotas a bloques en Org Babel.

¿Qué es org-babel-polyglot?

Este skill capacita a agentes de IA (como Claude Code, Cursor o Codex) para construir y gestionar pipelines de datos poliglotas utilizando Org Babel, el sistema de computación literaria de Emacs. Permite pasar datos sin problemas entre lenguajes como SQL, Python, R, Shell y Gnuplot dentro de un único documento Org, actuando Org Mode como bus de datos universal. El skill detalla el mecanismo de paso de variables mediante el argumento `:var`, el formato y preprocesamiento de tablas Org, y la creación de flujos de trabajo completos que van desde la consulta en bases de datos hasta la generación de gráficos. Además, cubre técnicas avanzadas como el uso de `#+CALL:` para invocar bloques como funciones reutilizables, la integración de fórmulas reactivas en tablas con `org-sbe`, el post-procesamiento de resultados con `:post`, y la reutilización de funciones a través de la Biblioteca de Babel. Es especialmente útil para automatizar análisis de datos reproducibles, generar informes dinámicos y orquestar tareas multi-herramienta sin salir del ecosistema Org.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pwquint24/org-babel-agent-skills/tree/HEAD/skills/org-babel-polyglot

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Pipelines de Datos Poliglotas e Interoperabilidad con Org Babel

Una de las capacidades más poderosas de Org Babel es la interoperabilidad agnóstica al lenguaje: los datos pueden fluir sin problemas a través de diferentes lenguajes de programación, tablas Org y fórmulas dentro del mismo documento.

Un solo cuaderno puede consultar datos en SQL, transformarlos y limpiarlos en Python, realizar modelos estadísticos en R, ejecutar comandos del sistema en Shell y visualizar resultados en Gnuplot o Matplotlib — con Org Mode actuando como el bus de datos universal.


1. El Mecanismo Universal de Paso de Datos: :var

El argumento de cabecera :var tiene una sintaxis idéntica en todos los lenguajes soportados:

:var NOMBRE_VARIABLE=ASIGNACIÓN
:var NOMBRE_VARIABLE=ARCHIVO:REFERENCIA

1.1 Tipos de Asignaciones Soportadas por :var

Fuente de EntradaEjemplo de SintaxisNotas
Valor Literal:var n=42 text="ejemplo"Números, booleanos y cadenas.
Tabla Org Nombrada:var data=mediciones_crudasPasa la tabla 2D como una lista anidada/data frame.
Lista Simple Nombrada:var items=lista_tareasPasa los elementos de la lista de nivel superior como un arreglo/vector.
Bloque de Código sin Args:var stats=calcular_estadisticas()Ejecuta calcular_estadisticas y pasa su valor de retorno.
Bloque de Código con Args:var res=calc(tasa=0.05, n=12)Evalúa el bloque destino con los parámetros especificados.
Contenido del Bloque / Literal:var plantilla=bloque_ejemplo[]Pasa el cuerpo textual de un bloque de ejemplo o código.
Evaluación de Emacs Lisp:var archivo=(buffer-file-name)Cualquier valor que comience con (, [, ' o ` se evalúa como Elisp.
Archivo Org Externo:var ext=otro.org:tabla_datosResuelve la referencia dentro de un archivo externo.

2. Pasando y Formateando Tablas Org

Las tablas Org se convierten automáticamente en estructuras nativas (listas de listas en Python, data frames en R, etc.). Los argumentos de cabecera controlan el preprocesamiento de la tabla:

2.1 Argumentos de Preprocesamiento de Tablas

  • :colnames yes | no | nil (Por defecto: nil):
    • Cuando es nil: Si la tabla tiene una regla horizontal debajo de la fila 1, Babel elimina los encabezados, convierte las filas y vuelve a aplicar los encabezados a las tablas devueltas.
    • Cuando es yes: Trata explícitamente la primera fila como nombres de columna / encabezados.
    • Cuando es no: Trata la primera fila como datos normales.
  • :rownames yes | no (Por defecto: no):
    • Cuando es yes: Elimina la primera columna antes de procesar y la restaura como nombres de fila al devolver.
  • :hlines yes | no (Por defecto: no):
    • Cuando es no (recomendado): Elimina todas las reglas horizontales (|-...) antes de pasar los datos al intérprete. Esto evita errores de tipo (como None o cadenas 'hline' que rompen rutinas numéricas).
    • Cuando es yes: Deja las reglas horizontales en su lugar como símbolos 'hline.

2.2 Rebanado e Indexado de Tablas en :var

Puedes rebanar filas y columnas directamente en la declaración :var usando la notación de índice basada en 0 [filas, columnas]:

#+NAME: conjunto_completo
| ID | Edad | Puntaje |
|----+------+---------|
|  1 |  25 |   88.5 |
|  2 |  30 |   92.0 |
|  3 |  22 |   79.0 |
|  4 |  35 |   95.5 |

# Pasando solo la columna 'Puntaje' (índice de columna 2, filas 1 hasta el final):
#+BEGIN_SRC python :var puntajes=conjunto_completo[1:, 2] :results value
  return sum(puntajes) / len(puntajes)
#+END_SRC

#+RESULTS:
: 88.75
  • Sintaxis de indexado:
    • data[0] : Primera fila.
    • data[,1] : Segunda columna en todas las filas.
    • data[1:3, :] : Filas 1 a 3, todas las columnas (inclusivo).
    • data[-1] : Última fila.
    • data[*] o data[0:-1] : Todas las filas.
  • Importante: El indexado ocurre antes de la eliminación de :colnames o :hlines.

3. Patrón de Pipeline Poliglota: SQL -> Python -> R -> Gráficos

Aquí hay un flujo de trabajo de datos completo en múltiples lenguajes:

#+TITLE: Pipeline Multilenguaje

* Paso 1: Consulta de Base de Datos (SQLite)
Extraer conteos de eventos crudos:

#+NAME: eventos_crudos
#+BEGIN_SRC sqlite :db telemetry.db :results table :colnames yes
  SELECT device_id, event_type, count(*) as count
  FROM events
  WHERE event_date >= '2025-01-01'
  GROUP BY device_id, event_type;
#+END_SRC

#+RESULTS: eventos_crudos
| device_id | event_type | count |
|-----------+------------+-------|
| dev-01    | heartbeat  |  1420 |
| dev-01    | alert      |    12 |
| dev-02    | heartbeat  |  1380 |
| dev-02    | alert      |    45 |

* Paso 2: Limpieza y Normalización de Datos (Python)
Consumir tabla SQLite en Python:

#+NAME: limpiar_telemetria
#+BEGIN_SRC python :var eventos=eventos_crudos :colnames yes :results value table
  cleaned = []
  for row in eventos:
      dev_id, ev_type, count = row[0], row[1], int(row[2])
      rate = round(count / 1440.0, 4)  # eventos por minuto
      cleaned.append([dev_id, ev_type, count, rate])
  return [["Device", "Event", "Count", "RatePerMin"]] + cleaned
#+END_SRC

#+RESULTS: limpiar_telemetria
| Device | Event     | Count | RatePerMin |
|--------+-----------+-------+------------|
| dev-01 | heartbeat |  1420 |     0.9861 |
| dev-01 | alert     |    12 |     0.0083 |
| dev-02 | heartbeat |  1380 |     0.9583 |
| dev-02 | alert     |    45 |     0.0313 |

* Paso 3: Modelado Estadístico (R)
Consumir la salida de Python limpia en R:

#+NAME: resumen_est_r
#+BEGIN_SRC R :var df=limpiar_telemetria :colnames yes :results value table
  summary_df <- aggregate(RatePerMin ~ Event, data=df, FUN=mean)
  colnames(summary_df) <- c("Event", "AvgRatePerMin")
  summary_df
#+END_SRC

#+RESULTS: resumen_est_r
| Event     | AvgRatePerMin |
|-----------+---------------|
| alert     |        0.0198 |
| heartbeat |        0.9722 |

4. Llamando Bloques Programáticamente: #+CALL: y call_ en Línea

Puedes tratar cualquier bloque nombrado como una función reutilizable e invocarlo sin reescribir el bloque.

4.1 Sintaxis

# Forma de bloque:
#+CALL: <nombre>[<cabeceras_evaluacion_interna>](<argumentos>) <cabeceras_resultado_final>

# Forma en línea:
... call_<nombre>[<cabeceras_evaluacion_interna>](<argumentos>)[<cabeceras_resultado_final>] ...
  • <nombre>: El #+NAME: del bloque destino.
  • <argumentos>: Parámetros estilo función, p.ej., (n=5, metric="accuracy").
  • [<cabeceras_evaluacion_interna>]: Se aplican durante la ejecución (p.ej., [:results output]).
  • [<cabeceras_resultado_final>]: Se aplican al formateo del resultado devuelto (p.ej., :results raw).

4.2 Ejemplo

#+NAME: calcular_potencia
#+BEGIN_SRC python :var base=2 exp=3 :results value
  return base ** exp
#+END_SRC

# Llamando con argumentos personalizados:
#+CALL: calcular_potencia(base=3, exp=4)

#+RESULTS:
: 81

# Invocación en línea:
La capacidad total es call_calcular_potencia(base=2, exp=8) unidades.

5. Hojas de Cálculo Reactivas: Babel en Fórmulas de Tabla (org-sbe)

Las tablas de Org Mode tienen una calculadora de hoja de cálculo incorporada (#+TBLFM:). La macro org-sbe permite que cualquier fórmula de celda de tabla llame a un bloque Babel arbitrario en cualquier lenguaje:

(org-sbe "nombre-bloque" (param1 valor1) (param2 valor2))
;; Abreviatura:
(sbe "nombre-bloque" (param1 valor1))

Ejemplo: Tabla Impulsada por Fórmulas en Python y R

#+NAME: tasa_impuesto_py
#+BEGIN_SRC python :var pais="US" :results value
  rates = {"US": 0.08, "UK": 0.20, "DE": 0.19}
  return rates.get(pais, 0.0)
#+END_SRC

#+NAME: tabla_factura
| Artículo     | País | Precio Base | Tasa Impuesto | Precio Total |
|--------------+------+-------------+---------------+--------------|
| Nodo Servidor| US   |        1200 |          0.08 |       1296.0 |
| SAN Almacen. | UK   |        3000 |           0.2 |       3600.0 |
| Pasarela     | DE   |         800 |          0.19 |        952.0 |
#+TBLFM: $4='(org-sbe "tasa_impuesto_py" (pais $"$2")) :: $5=$3 * (1 + $4)
  • ¡En la tabla, presionar C-u C-c C-c en la línea #+TBLFM recalcula todas las fórmulas, evaluando el bloque de Python dinámicamente para cada fila!
  • $"$2" pasa el valor de la columna 2 como una cadena literal.

6. Post-Procesamiento de Resultados con :post

El argumento de cabecera :post encadena la salida de un bloque a través de un bloque de formateo secundario antes de insertarla en el documento. La salida del bloque primario se vincula a *this*:

# Bloque post-procesador que agrega atributos de exportación LaTeX personalizados:
#+NAME: envolver_figura_latex
#+BEGIN_SRC emacs-lisp :var data="" caption="Figura"
  (format "#+CAPTION: %s\n#+ATTR_LATEX: :width 0.8\\textwidth\n%s" caption data)
#+END_SRC

# Bloque de trazado primario usando :post:
#+BEGIN_SRC python :results file link :file figures/out.pdf :post envolver_figura_latex(caption="Precisión del Modelo", data=*this*)
  import matplotlib.pyplot as plt
  plt.plot([1, 2, 3], [4, 5, 6])
  plt.savefig("figures/out.pdf")
  plt.close()
  return "figures/out.pdf"
#+END_SRC

7. La Biblioteca de Babel: Bibliotecas de Funciones Globales Compartidas

La Biblioteca de Babel te permite importar y compartir bloques nombrados a través de múltiples archivos .org distintos sin duplicar código.

  1. Crea un archivo de biblioteca compartida (p.ej., ~/org/biblioteca_compartida.org) que contenga bloques nombrados.
  2. Ingiere la biblioteca en tu sesión de Emacs:
    (org-babel-lob-ingest "~/org/biblioteca_compartida.org")
    
    O mediante el atajo de teclado: C-c C-v i (org-babel-lob-ingest).
  3. ¡Llama a cualquier bloque de ese archivo usando #+CALL: nombre_bloque(args) en cualquier búfer!

8. Errores Comunes en Pipelines Poliglotas y Mejores Prácticas

ErrorConsecuenciaSolución
Encabezados de columna no coincidentesLos cálculos numéricos fallan porque las cadenas de encabezado se leen como datos de la fila 0Siempre especifica :colnames yes en los bloques que consumen entradas tabulares.
Reglas horizontales de tabla (`-`) causan fallosPython/R recibe el símbolo 'hline donde se esperaba un número
Bloques sin nombre en :varError Reference 'xyz' not found in bufferAsegúrate de que el bloque o tabla de entrada tenga una palabra clave #+NAME: xyz coincidente justo encima.
Comillas en variables de celda de tabla en org-sbeLas celdas de texto sin comillas se leen como símbolos Lisp indefinidosEnvuelve las referencias de columna en cadenas: (pais $"$2").
Orden de indexado con encabezadosdata[0] devuelve la fila de encabezado al indexarTen en cuenta que el rebanado de tablas ocurre antes de la eliminación de :colnames.

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Skills relacionados