Chunks: R y Python en el mismo documento
Anatomía de un chunk
```{r}
#| label: fig-cars
#| echo: false
#| fig-cap: "Distancia de frenado en función de la velocidad."
#| fig-width: 6
#| fig-height: 4
plot(cars, pch = 16, col = "#5F8575")
```
Tres partes:
{r}(o{python},{julia}, etc.), el motor.- Opciones con
#|: configuración del chunk. - Código: el cuerpo.
Las opciones #| son la sintaxis moderna de Quarto. Antes (en Rmd) iban dentro de {r, opcion=valor}. Ahora una por línea, comentadas con #|. Mucho más legible cuando hay 4-5 opciones.
Las opciones que importan
echo: mostrar o no el código
#| echo: true # default: muestra
#| echo: false # oculta el código, muestra solo el output
Para informes ejecutivos (lector no técnico), echo: false en todos los chunks. Para documentación o tutorial, echo: true. Para reportes mixtos, echo: fenced muestra el chunk completo incluyendo las opciones.
eval: ejecutar o no
#| eval: true # default
#| eval: false # muestra código sin ejecutar
Útil para mostrar código de ejemplo sin que se ejecute (porque depende de archivos que no están, o porque es solo ilustrativo).
output: cómo va el output
#| output: true # default: muestra el output normalmente
#| output: false # oculta el output
#| output: asis # interpreta el output como markdown directamente
output: asis es el truco para que un chunk que devuelve texto markdown se integre como markdown. Útil para generar secciones programáticamente.
warning, message, error: el ruido
#| warning: false
#| message: false
#| error: true # permite que el render continúe aunque haya error
Para informes finales, warning: false y message: false globales en el front matter, son los más usados. El ruido de carga de paquetes no aporta.
error: true es útil cuando el documento enseña errores (un tutorial), el render no muere al primer error.
include: el todo o nada
#| include: false
include: false ejecuta el chunk pero no incluye nada en el output, ni código ni resultado. Útil para setup invisible (cargar paquetes, configurar opciones).
Setup: el primer chunk típico
El chunk de configuración global:
```{r}
#| label: setup
#| include: false
library(tidyverse)
library(here)
knitr::opts_chunk$set(
echo = FALSE,
message = FALSE,
warning = FALSE,
fig.align = "center"
)
theme_set(theme_minimal(base_size = 12))
```
label: setup: nombre del chunk. Útil para referencia y para tracking de tiempos.include: false: invisible.- Carga de paquetes + opciones globales en un solo bloque.
Quarto respeta knitr::opts_chunk$set() del chunk setup. Es el patrón heredado de Rmd y sigue siendo válido. Alternativa: poner execute: en el front matter (más Quarto-nativo).
Figuras: control fino
```{r}
#| label: fig-tendencia
#| fig-cap: "Tendencia de ventas mensuales 2024."
#| fig-width: 8
#| fig-height: 5
#| fig-align: center
#| fig-dpi: 300
#| out-width: 80%
ggplot(datos, aes(mes, ventas)) +
geom_line() +
geom_point()
```
Opciones de figura:
fig-cap: caption mostrado debajo.fig-width,fig-height: tamaño en pulgadas al renderizar.fig-align:default/left/center/right.fig-dpi: resolución. 300 para PDF print, 96-120 para web.out-width: tamaño al mostrarse (% del contenedor).
Para varias figuras en un chunk (subfiguras):
```{r}
#| label: fig-multi
#| fig-cap: "Distribución de ventas."
#| fig-subcap:
#| - "Por región"
#| - "Por trimestre"
#| layout-ncol: 2
ggplot(datos, aes(region, ventas)) + geom_boxplot()
ggplot(datos, aes(trimestre, ventas)) + geom_boxplot()
```
Dos figuras lado a lado con caption combinada. Patrón muy útil para reports.
Tablas
Para tablas a partir de un data.frame, knitr::kable() da el formato base:
```{r}
#| label: tbl-resumen
#| tbl-cap: "Resumen estadístico por grupo."
resumen |>
knitr::kable(digits = 2,
col.names = c("Grupo", "Media", "Desv. típica", "N"))
```
Mejores: gt para HTML elegante, flextable para Word con control fino, kableExtra para PDF/LaTeX. Veremos esto en el tutorial 4 (figuras y tablas publicables).
Python en Quarto
Para usar Python necesitas:
- Python instalado (3.10+).
- Jupyter (
pip install jupyterouv add jupyter). - Kernel detectable.
Chunk Python:
```{python}
import pandas as pd
import seaborn as sns
df = sns.load_dataset("penguins")
df.head()
```
Mismas opciones (#| echo, #| fig-cap, etc.). Lo único distinto es {python} en lugar de {r}.
Mismo documento, R + Python
Sí, conviven:
```{r}
library(dplyr)
df_r <- mtcars |> as_tibble()
```
```{python}
import pandas as pd
df_py = pd.DataFrame({"x": [1, 2, 3]})
```
Cada chunk usa su motor. Por defecto los entornos están separados, el df_r de R no es visible desde Python y viceversa.
Pasar datos entre R y Python con reticulate
Si quieres compartir variables:
```{r}
library(reticulate)
df_r <- mtcars
```
```{python}
# acceso al objeto R desde Python
df_py = r.df_r
df_py.head()
```
```{r}
# acceso al objeto Python desde R
head(py$df_py)
```
r.objeto para acceder al espacio de R desde Python. py$objeto para el revés desde R. reticulate hace conversiones razonables (data.frame R ↔︎ DataFrame pandas, vector ↔︎ list, etc.).
Es la forma elegante de tener R y Python en el mismo análisis. Aunque para análisis serio mixto, normalmente se separa en archivos distintos y se exporta vía Parquet.
Engines: knitr vs jupyter
Quarto puede usar dos motores:
knitr(default si hay chunks de R), motor histórico, soporta R nativo + Python (vía reticulate).jupyter(default si solo hay Python), motor Jupyter, no soporta R.
Para forzar:
engine: knitr # o jupyterRecomendación: si tu documento es R o R+Python, usa knitr. Si es solo Python, jupyter. La diferencia más visible: jupyter reproduce exactamente lo que verías en un notebook Jupyter (incluido el output rico de IPython). knitr es más limpio textualmente.
Cache: evitar recalcular
Si un chunk es lento, cache: true:
```{r}
#| label: modelo
#| cache: true
modelo <- DESeq(dds) # toma minutos
```
knitr guarda el resultado en disco. Render sucesivo: si el código y dependencias no cambian, no se recalcula.
Lo veremos a fondo en el tutorial 8 (cache y freeze). Mención aquí porque resuelve el problema más común al iterar documentos largos.
Chunk hooks: lo que knitr puede hacer
Hooks útiles preconfigurados:
```{r}
#| label: fig-elegante
#| dev: cairo_pdf
#| fig-format: pdf
#| dpi: 300
ggplot(...) + ...
```
dev: el device gráfico.cairo_pdfpara PDFs con transparencia bien gestionada.ragg_pngpara PNGs con mejor texto.fig-format: formato de archivo.png,pdf,svg. En HTML,svgda vectoriales escalables.
Nombrar chunks: la disciplina que paga
Cada chunk debería tener label:
#| label: limpiar-datos
#| label: fig-distribucion
#| label: tbl-resumen
Convenciones:
fig-*para figuras (necesario para cross-references).tbl-*para tablas (idem).- Nombre descriptivo para los demás. Sin espacios, en minúsculas, con guiones.
Cuando un chunk falla en render, Quarto te dice “error in chunk X”, con buenos nombres lo encuentras en segundos.
Trampas habituales
- Mezclar sintaxis vieja (
{r, echo=FALSE}) y nueva (#| echo: false) en el mismo doc. Ambas funcionan pero conviene unificar a la nueva. include: falsecuando queríasecho: false.include: falseno muestra nada del chunk.echo: falsesolo oculta el código pero muestra el output. Confusión frecuente.- Olvidar
knitr::opts_chunk$set()ensetup. Lleva a definir lo mismo en cada chunk. Pon defaults globalmente. - Cache habilitado con dependencias mal declaradas. Si tu chunk depende del output de otro y cambias el de arriba, el de abajo no se recalcula.
dependson: c("otro_chunk")resuelve. {python}sin Jupyter instalado. Error claro pero confuso si no sabes que necesitas Jupyter.pip install jupytero equivalente.
En la siguiente entrega
Tienes los chunks bajo control. Lo siguiente: figuras y tablas publicables, gt, flextable, kableExtra, ggplot exportado con calidad, gestión de captions y referencias. Lo que distingue un informe profesional de uno funcional. Lo siguiente.