ComdTeX

Tablas desde datos

Un bloque :::csv no pega una copia de tus datos en el documento. Guarda una selección: qué archivo, qué columnas, qué filas. Cuando el CSV subyacente cambia, el siguiente render o exportación vuelve a leer el archivo y la tabla se actualiza sola. Nunca vuelves a copiar números, y el documento nunca se desincroniza de la hoja de cálculo que los produjo.

Sintaxis

Un bloque nombra el archivo y, opcionalmente, un selector de columnas y un selector de filas, cada uno agrupado entre paréntesis:

:::csv[Growth rates]
data.csv (A:B, D) (1:8, 12)
:::

El [Growth rates] opcional se convierte en el título de la tabla. data.csv se resuelve como un archivo del vault, de la misma forma en que la transclusión resuelve notas. (A:B, D) selecciona las columnas A, B y D; (1:8, 12) selecciona las filas de datos 1 a 8 más la fila 12.

Formas de selector

FormaSignificado
A:BUn rango contiguo, con letras de hoja de cálculo o índices base 1 (A:B, 1:3)
(A, C, F)Una lista no contigua, agrupada entre paréntesis
NombreUn nombre de encabezado, comparado sin distinguir mayúsculas contra la fila de encabezado del CSV
1, 2, …Un índice base 1: para columnas, posición en la hoja de cálculo; para filas, posición entre las filas de datos (la fila de encabezado no es la fila 1)
1:8 o (1:3, 7)Los rangos de filas funcionan igual que los de columnas, más agrupación no contigua
(omitido)Omitir un selector por completo significa “todo”: data.csv solo selecciona todas las columnas y todas las filas
(C, A)El orden se conserva, así que esto reordena la tabla: la columna C va primero, la columna A segundo

Una palabra suelta puede coincidir con una letra de hoja de cálculo o con un nombre de encabezado; el nombre de encabezado gana cuando ambos son posibles, así que un CSV con una columna literalmente llamada A se comporta como tú esperarías.

La forma legible de clave/valor es equivalente a la compacta, y se lee mejor cuando una selección se alarga:

:::csv[Growth rates]
file: data.csv
cols: A:B, D
rows: 1:8, 12
:::

Datasets con nombre

Cuando varios bloques necesitan el mismo recorte de un CSV, un bloque :::data{#data:growth} declara esa selección una sola vez y le da un nombre:

:::data{#data:growth}
growth.csv (A:D) (1:20)
:::

La declaración no imprime nada. Como una definición de macro, existe solo para que otros bloques apunten a ella: un :::csv cuyo origen es @data:growth renderiza esos datos como tabla, y un bloque de gráfica puede hacer lo mismo. La selección propia del bloque que la usa se aplica encima de la del dataset, así que @data:growth (A, C) significa “las columnas A y C de mi dataset growth”, no las columnas A y C del CSV completo:

:::csv[Cepas rápidas]
@data:growth (A, C)
:::

Un dataset es deliberadamente distinto de una figura, una ecuación o una tabla: no es un elemento numerado y nadie lo cita en prosa, así que no encontrarás un “ver Data 3”. Pero sí viaja en el mismo sistema de labels que el resto del editor: el panel de Labels reporta declaraciones duplicadas (dos bloques :::data con el mismo {#data:nombre}), referencias a datasets que no existen (@data:algo sin una declaración correspondiente) y datasets que nadie usa. El editor marca ambos problemas mientras escribes, no solo al abrir el panel.

Una tabla generada por :::csv también puede llevar su propio label, {#tbl:x}, y volverse citable con @tbl:x en la prosa, exactamente como una tabla escrita a mano. El dataset que la alimenta y la tabla que produce son dos cosas distintas: una no se numera ni se cita, la otra sí.

Analizando el CSV en sí

Los archivos se leen según RFC 4180: campos entre comillas, comillas escapadas, y campos que contienen el delimitador o saltos de línea incrustados se manejan correctamente. El delimitador en sí no se asume como coma: ComdTeX lo detecta contando candidatos en la primera línea, eligiendo entre coma, punto y coma, tabulador y barra vertical. Un CSV exportado desde una hoja de cálculo europea con punto y coma, o un TSV, funcionan ambos sin ninguna configuración adicional.

Cuando falta algo

Un archivo faltante no falla en silencio. Si data.csv no se encuentra en el vault, el bloque se reemplaza por una nota visible que lo dice, en lugar de la tabla. Lo mismo ocurre con una selección que no resuelve a nada, o un archivo que no se puede leer como CSV. El silencio parecería un error de renderizado; una nota honesta te dice exactamente qué corregir.

Dónde se resuelve

Un bloque :::csv se resuelve de forma consistente en todas partes: la vista previa en vivo, “Compilar PDF”, “Exportar como .tex”, “Exportar PDF” y cualquier otra ruta de exportación. También se resuelve dentro de notas transcluidas: si la nota A incrusta la nota B con ![[B]], y B contiene un bloque :::csv, ese bloque igual se expande correctamente cuando A se renderiza o se exporta. Esto es deliberado: todas las rutas de exportación pasan por el mismo paso de resolución de documento, así que la tabla que ves en la vista previa es exactamente la tabla que llega al PDF, sin importar qué botón hayas presionado para llegar ahí.

Valores sueltos de archivos de resultados

Una tabla es una forma de traer un archivo de resultados al texto. La otra es un solo número: una n, un valor p, una exactitud. Escritos a mano, quedan desactualizados el día que el análisis se vuelve a ejecutar. val() los lee del archivo:

:::data{#data:stats}
results/stats.csv
:::

La diferencia fue significativa (val(stats, pvalue, p)), con n = val(stats, n).

El primer argumento es el nombre de un dataset declarado con :::data (stats, data:stats y @data:stats significan el mismo dataset). La declaración dice dónde está el archivo; cada val() lee a través de ella. ComdTeX nunca ejecuta tu código: solo lee el archivo que escribió tu pipeline.

Direccionar un valor

LlamadaSignificado
val(stats, pvalue)Clave de fila: la fila cuya primera columna es pvalue, con el valor de la segunda columna (un archivo metric,value)
val(stats, effect, ci)Clave de fila más una columna: nombre del encabezado, letra o número
val(stats, B4)Celda de hoja de cálculo. La fila 1 es la línea de encabezado, como la muestra una hoja de cálculo
val(stats, "B4")Las comillas fuerzan la lectura como clave de fila, para una clave que parece una celda
val(fit, metrics.auc)Dataset JSON: una ruta con puntos (folds.0.acc y folds[0].acc funcionan)

Las claves de fila no distinguen mayúsculas de minúsculas. El JSON solo lo lee val(): una tabla :::csv o una gráfica no pueden usar un dataset JSON. Una ruta que llega a un objeto o a una lista, en vez de a un valor único, cuenta como valor ausente.

Formatos

Un último argumento opcional da formato al número:

FormatoResultado
3sfTres cifras significativas (cualquier cantidad desde 1)
.2fDos decimales
.2eNotación científica con dos decimales (e sola conserva todos los dígitos)
pUn valor p: p = 0.032, o p < 0.001 por debajo de ese umbral. Un valor fuera de 0 a 1 se reporta como no válido

La notación científica y p necesitan modo matemático, así que fuera de $...$ se envuelven en él por ti. Sin formato, se imprime el texto de la celda tal como está en el archivo.

Dónde funciona

val() funciona en prosa, dentro de fórmulas y dentro de otros shorthands, así que se combina con unidades: si(val(stats, effect, 3sf), mg/L) (ver Unidades, química y convenciones). Los valores se rellenan antes de procesar cualquier otra cosa, así que la vista previa y todas las exportaciones imprimen el mismo número. Un val() dentro de una nota transcluida se resuelve contra el dataset declarado en la nota que la incrusta.

Un val() con un solo argumento se deja tal cual, porque val(x) es mucho más probablemente una fórmula. Los bloques de código y el código en línea tampoco se tocan, así que puedes documentar la sintaxis.

Límites y valores ausentes

  • El archivo se lee, no se recalcula. Si el pipeline no se ha ejecutado, el documento muestra los números viejos.
  • Los archivos de resultados se vuelven a leer cuando la ventana de ComdTeX recupera el foco, así que después de volver a ejecutar tu análisis, regresa a la ventana para refrescar.
  • Un dataset ausente, un archivo ausente, un archivo ilegible, una celda ausente o una celda que no es un número (cuando se pide un formato) nunca desaparece: la llamada se reemplaza por una nota visible como [stats, pvalue: no value at pvalue], y el editor muestra un aviso.

Tables from data

A :::csv block does not paste a copy of your data into the document. It stores a selection: which file, which columns, which rows. When the underlying CSV changes, the next render or export reads the file again and the table updates on its own. You never re-copy numbers, and the document never drifts from the spreadsheet that produced them.

Syntax

A block names the file and, optionally, a column selector and a row selector, each grouped in parentheses:

:::csv[Growth rates]
data.csv (A:B, D) (1:8, 12)
:::

The optional [Growth rates] becomes the table’s caption. data.csv is resolved as a vault file, the same way transclusion resolves notes. (A:B, D) selects columns A, B and D; (1:8, 12) selects data rows 1 through 8 plus row 12.

Selector forms

FormMeaning
A:BA contiguous range, spreadsheet letters or 1-based indices (A:B, 1:3)
(A, C, F)A non-contiguous list, grouped in parentheses
NameA header name, matched case-insensitively against the CSV’s header row
1, 2, …A 1-based index: for columns, spreadsheet position; for rows, position among the data rows (the header row is not row 1)
1:8 or (1:3, 7)Row ranges work the same way as column ranges, plus non-contiguous grouping
(omitted)Leaving a selector out entirely means “everything”: data.csv alone selects every column and every row
(C, A)Order is preserved, so this reorders the table: column C comes first, column A second

A bare word can match either a spreadsheet letter or a header name; the header name wins when both are possible, so a CSV with a column literally named A behaves the way you would expect.

The readable key/value form is equivalent to the compact one, and reads better when a selection gets long:

:::csv[Growth rates]
file: data.csv
cols: A:B, D
rows: 1:8, 12
:::

Named datasets

When several blocks need the same slice of a CSV, a :::data{#data:growth} block declares that selection once and gives it a name:

:::data{#data:growth}
growth.csv (A:D) (1:20)
:::

The declaration prints nothing. Like a macro definition, it exists only so other blocks can point at it: a :::csv block whose source is @data:growth renders that data as a table, and a plot block can do the same. The referencing block’s own selection applies on top of the dataset’s, so @data:growth (A, C) means “columns A and C of my growth dataset”, not columns A and C of the whole CSV:

:::csv[Fast strains]
@data:growth (A, C)
:::

A dataset is deliberately different from a figure, an equation or a table: it is not a numbered element and nobody cites it in prose, so you will never find a “see Data 3”. But it does ride the same label system as the rest of the editor: the Labels panel reports duplicate declarations (two :::data blocks with the same {#data:name}), references to datasets that do not exist (@data:something with no matching declaration), and datasets nobody uses. The editor flags both mistakes while you write, not only when you open the panel.

A table generated by :::csv can also carry its own label, {#tbl:x}, and become citable with @tbl:x in prose, exactly like a hand-written table. The dataset that feeds it and the table it produces are two different things: one is never numbered or cited, the other is.

Parsing the CSV itself

Files are read as RFC 4180: quoted fields, escaped quotes, and fields containing the delimiter or embedded newlines are all handled correctly. The delimiter itself is not assumed to be a comma: ComdTeX sniffs it by counting candidates in the first line, choosing among comma, semicolon, tab and pipe. A CSV exported from a European spreadsheet with semicolons, or a TSV, both work without any extra configuration.

When something is missing

A missing file does not fail silently. If data.csv cannot be found in the vault, the block is replaced with a visible note saying so, in place of the table. The same happens for a selection that resolves to nothing, or a file that cannot be read as CSV. Silence would look like a rendering bug; an honest note tells you exactly what to fix.

Where it resolves

A :::csv block resolves consistently everywhere: the live preview, “Compile PDF”, “Export as .tex”, “Export PDF”, and every other export path. It also resolves inside transcluded notes: if note A embeds note B with ![[B]], and B contains a :::csv block, that block still expands correctly when A is rendered or exported. This is deliberate: every export path calls through the same document-resolution step, so a table you see in the preview is exactly the table that reaches the PDF, regardless of which button you pressed to get there.

Single values from results files

A table is one way to bring a results file into the text. The other is a single number: an n, a p-value, an accuracy. Typed by hand, these go stale the day the analysis runs again. val() reads them from the file instead:

:::data{#data:stats}
results/stats.csv
:::

The difference was significant (val(stats, pvalue, p)), with n = val(stats, n).

The first argument is the name of a dataset declared with :::data (stats, data:stats and @data:stats all mean the same dataset). The declaration says where the file is; every val() reads through it. ComdTeX never runs your code: it only reads the file your pipeline wrote.

Addressing a value

CallMeaning
val(stats, pvalue)Row key: the row whose first column is pvalue, value from the second column (a metric,value file)
val(stats, effect, ci)Row key plus a column: header name, letter or number
val(stats, B4)Spreadsheet cell. Row 1 is the header line, as a spreadsheet shows it
val(stats, "B4")Quotes force the row-key reading, for a key that looks like a cell
val(fit, metrics.auc)JSON dataset: a dotted path (folds.0.acc and folds[0].acc both work)

Row keys are matched case-insensitively. JSON is read only by val(): a :::csv table or a plot cannot use a JSON dataset. A path that lands on an object or array, rather than a single value, counts as missing.

Formats

An optional last argument formats the number:

FormatResult
3sfThree significant figures (any count from 1)
.2fTwo decimals
.2eScientific notation with two decimals (e alone keeps all digits)
pA p-value: p = 0.032, or p < 0.001 below that. A value outside 0 to 1 is reported as not valid

Scientific notation and p need math, so outside $...$ they are wrapped in it for you. Without a format, the cell text is printed as it is in the file.

Where it works

val() works in prose, inside math and inside other shorthands, so it composes with units: si(val(stats, effect, 3sf), mg/L) (see Units and conventions). The values are filled in before anything else is processed, so the preview and every export print the same number. A val() inside a transcluded note resolves against the dataset declared in the note that embeds it.

A val() with a single argument is left alone, since val(x) is far more likely to be math. Code blocks and inline code are also left alone, so you can document the syntax.

Limits and missing values

  • The file is read, not recalculated. If the pipeline has not run, the document shows the old numbers.
  • Results files are re-read when the ComdTeX window regains focus, so after rerunning your analysis, switch back to the window to refresh.
  • A missing dataset, a missing file, an unreadable file, a missing cell or a cell that is not a number (when a format is asked for) never disappears: the call is replaced by a visible note such as [stats, pvalue: no value at pvalue], and the editor shows a warning.