stat — un número para toda la ejecución
Úsalo cuando una fila necesita saber algo de todas las filas, incluidas las que vienen después: si este precio está por encima de la media, cuál es el pedido más grande del fichero, cuántas filas llevan valor.
Este es el tercer y último eje de "un valor que no se sortea, sino que se deriva".
accumulate= suma una lista dentro de un registro. running suma una
columna sobre la marcha, así que la fila 40 sabe de las filas 1–39. Una estadística sabe de
todas.
<tdc>
<env count="8" seed="basket" local="en">
<sequence name="Price"><gen type="number" value="10..200" decimals="2"/></sequence>
<sequence name="Average"><gen type="stat" of="Price" op="mean" decimals="2"/></sequence>
<sequence name="Verdict">
<gen if="Price > Average" type="text" value="above average"/>
<gen type="text" value="below average"/>
</sequence>
</env>
<block>
<line><data>${{Price}} ${{Average}} ${{Verdict}}</data></line>
</block>
</tdc>
156.83 122.52 above average 176.51 122.52 above average 135.17 122.52 above average 157.94 122.52 above average 50.71 122.52 below average 92.28 122.52 below average 50.37 122.52 below average 160.35 122.52 above average
"¿Está esta fila por encima de la media?" no se puede preguntar de otra forma. La media no
se conoce hasta que existe la última fila, y un <gen> condicional se evalúa mientras la
fila se construye — así que la estadística tiene que ser una columna propia, calculada
antes.
Los valores vienen de un seed fijo, así que son reproducibles, pero las cadenas exactas
pueden cambiar entre versiones del núcleo. Tómalos como ejemplos de forma, no como
garantías.
De un vistazo
| Atributo | Obligatorio | Qué hace |
|---|---|---|
of | sí | La columna a resumir. Debe estar declarada arriba de esta secuencia |
op | sí | sum, mean, median, min, max, count o stddev |
decimals | no | Redondear la respuesta a N decimales, de 0 a 10 |
Una estadística no sortea nada. Lee una columna que ya existe, no consume nada de aleatoriedad y por tanto añadirla deja todas las demás columnas exactamente donde estaban.
Las siete estadísticas
<env count="6" seed="lab" local="en">
<sequence name="Reading"><gen type="number" value="1..100"/></sequence>
<sequence name="Total"><gen type="stat" of="Reading" op="sum"/></sequence>
<sequence name="Smallest"><gen type="stat" of="Reading" op="min"/></sequence>
<sequence name="Largest"><gen type="stat" of="Reading" op="max"/></sequence>
<sequence name="Middle"><gen type="stat" of="Reading" op="median"/></sequence>
<sequence name="Spread"><gen type="stat" of="Reading" op="stddev" decimals="3"/></sequence>
<sequence name="Rows"><gen type="stat" of="Reading" op="count"/></sequence>
</env>
60 sum=297 min=7 max=81 median=63 sd=27.415 n=6 81 sum=297 min=7 max=81 median=63 sd=27.415 n=6 66 sum=297 min=7 max=81 median=63 sd=27.415 n=6 7 sum=297 min=7 max=81 median=63 sd=27.415 n=6 17 sum=297 min=7 max=81 median=63 sd=27.415 n=6 66 sum=297 min=7 max=81 median=63 sd=27.415 n=6
Dos de ellas conviene decirlas en voz alta, porque las alternativas son igual de comunes y dan números distintos:
stddeves la desviación típica POBLACIONAL — dividida por n, no por n−1. Una columna generada es todo lo que describe, no una muestra sacada de algo mayor, así que n es el divisor honesto. La misma decisión que toma la funciónstddev()de las expresiones.mediancon un número par de valores es la media de los dos centrales, así que una columna2,4,4,4,5,5,7,9tiene mediana4.5.
count es cuántas filas llevaban valor: las filas que un filtro
parent vació no se cuentan, y tampoco
participan en ninguna de las demás. Es la misma regla que siguen accumulate= y running,
así que una columna filtrada significa una sola cosa en las tres y no tres distintas.
Céntimos exactos y decimals=
sum, min y max son el último valor de la columna acumulada correspondiente. No es
un atajo: es lo que impide que las dos funciones se separen. La aritmética va sobre enteros
escalados por la fracción más larga de la columna, nunca sobre coma flotante, así que
19.99 + 0.01 + 0.01 es 20.01 en las cinco implementaciones y no 20.009999999999998 en
una de ellas. min y max devuelven un elemento que ya existe, así que un valor que llegó
como 007 sigue siendo 007.
mean, median y stddev son razones y no pueden ser exactas. Sin decimals= se
imprimen enteras, con todos sus dígitos, porque una media que perdió dígitos en silencio es
peor que una fea. Con decimals= se redondean — y un medio va alejándose del cero, la
misma regla que sigue round() en todo TDC, así que 117.045 a dos decimales es 117.05.
Orden de declaración
of= nombra una columna, y debe estar declarada arriba de la estadística (TDC240) —
la misma regla que siguen parent y running,
por la misma razón: la estadística se construye a partir de una columna que ya existe.
Una estadística que no dice qué resumir, o qué estadística tomar, es TDC262.
error[TDC262]: op="men" is not one of sum, mean, median, min, max, count, stddev --> lab.tdc:4:63 | 4 | <sequence name="Spread"><gen type="stat" of="Reading" op="men"/></sequence> | ^^^ | help: did you mean "mean"? note: One of: sum, mean, median, min, max, count, stddev.
Qué motor la ejecuta
El motor de streaming rechaza una estadística, por su nombre, y el enrutador manda la configuración al motor en memoria:
tdcv2: a statistic ("Average") is computed over every row of the run, including the ones after this one, so it cannot be computed one row at a time; the in-memory engine handles it (run without a forced streaming engine)Normalmente nunca ves ese mensaje — el enrutador elige el motor por su cuenta, y el rechazo solo sale a la superficie cuando una configuración nombra un motor de streaming y por tanto ha pedido que se lo expliquen.
Lo que cuesta es el mismo límite que tiene running,
un paso más fuerte: un total acumulado al menos conoce su respuesta cuando llega a una
fila, y una estadística no la conoce hasta que la ejecución termina. La columna que lee se
mantiene durante toda la ejecución.
Todo lo demás sigue fluyendo. El límite es por configuración, no por proyecto: una ejecución sin estadística no se ve afectada.
Véase también
running— la misma columna, acumulada sobre la marcha en lugar de resumida al finalaccumulate=sobre una listarepeat— la misma idea dentro de un registro, gratis en cualquier motor- Expresiones —
sum,mean,medianystddevtambién existen como funciones, sobre una lista dentro de una fila y no sobre una columna