Datos faltantes — missing
Se usa cuando necesita probar cómo aguanta su código los huecos. Los datos reales
casi nunca están completos: un teléfono que nunca se capturó, un ingreso que se perdió,
un campo simplemente en blanco. Si solo prueba con filas «perfectas», el primer null en
producción rompe todo. El atributo missing mezcla vacíos a propósito para que
usted vea la falla antes que sus usuarios.
missing es un atributo transversal: funciona en cualquier
<gen>, sea lo que sea lo que genere.
Las salidas de ejemplo de abajo son ilustrativas: las filas exactas que produce un
seed dado pueden cambiar entre versiones del core, pero el comportamiento que el
atributo garantiza no cambia.
- Ala serie limpia
- Bcon anomaly= — los puntos marcados son los valores atípicos inyectados
- Ccon missing= — las marcas de abajo son filas que no produjeron ningún valor
Cómo activarlo
Ponga missing="p" en un <gen>, donde p es una fracción de 0 a 1 — la
proporción de valores que quedan vacíos:
<gen type="number" value="30000..90000" missing="0.3"/>
Alrededor del 30% de los ingresos sale vacío; el resto son números ordinarios.
Cada valor se descarta de forma independiente con esa probabilidad. En estadística esto se llama MCAR — Missing Completely At Random, «faltantes completamente al azar» — los huecos caen sin ninguna relación con otro campo ni con el valor mismo.
Por omisión, un valor faltante es un string vacío. ¿Quiere su propio marcador
(NULL, NA, —)? Use missing_as — vea abajo.
Antes y después — qué cambia realmente un vacío
El problema. Hasta que no vea el mismo campo «entero» y «agujerado» uno junto al otro, es difícil saber qué está pasando: qué valor se perdió y cuál nunca estuvo ahí.
La herramienta. Tome una lista de ciudades y arme dos columnas a partir de ella:
Full tal cual, y Holey — la misma lista con missing.
order="sequential" recorre la lista estrictamente en orden, así
que las dos columnas se alinean fila por fila y usted ve exactamente qué se cayó:
<env count="8" seed="demo">
<sequence name="Full"> <gen type="text" value="Toluca,Mérida,Colima,Puebla,Durango,Morelia,Tijuana,Cancún" order="sequential"/></sequence>
<sequence name="Holey"><gen type="text" value="Toluca,Mérida,Colima,Puebla,Durango,Morelia,Tijuana,Cancún" order="sequential" missing="0.4"/></sequence>
</env>
...
<data>full=${{Full}} | holey=${{Holey}}</data>
full=Toluca | holey=Toluca full=Mérida | holey=Mérida full=Colima | holey= full=Puebla | holey= full=Durango | holey=Durango full=Morelia | holey=Morelia full=Tijuana | holey=Tijuana full=Cancún | holey=Cancún
A la izquierda todo está en su lugar; a la derecha las mismas filas, pero Colima y
Puebla desaparecieron. El valor no se cambió por otro ni se recorrió hacia arriba:
simplemente quedó vacío. (En 8 filas con missing="0.4" se cayeron dos — la proporción
es aleatoria, y en una muestra chica la dispersión es amplia.)
Un marcador visible — missing_as
El problema. Un string vacío es invisible en una exportación: en un CSV es nada más
«nada entre dos comas», y a simple vista no se distingue un vacío de un valor corto. Los
datasets reales suelen señalar el hueco de forma explícita — NULL, NA, —.
La herramienta. missing_as="marcador" imprime su texto donde iría el vacío. Las
filas que se pierden son las mismas (las elige el seed y el nombre de la columna,
no el marcador); lo único que cambia es qué queda parado en el hueco:
mask= y case= corren después de rellenar el hueco, así que también reforman el
marcador: missing_as="n/a" case="upper" escribe N/A. Escriba el marcador tal como
quiere que aparezca y, si una máscara lo estropea, ponga el formato en una secuencia
aparte.
<sequence name="Holey">
<gen type="text" value="Toluca,Mérida,Colima,Puebla,Durango,Morelia,Tijuana,Cancún"
order="sequential" missing="0.4" missing_as="NULL"/>
</sequence>
full=Toluca | holey=Toluca full=Mérida | holey=Mérida full=Colima | holey=NULL full=Puebla | holey=NULL full=Durango | holey=Durango full=Morelia | holey=Morelia full=Tijuana | holey=Tijuana full=Cancún | holey=Cancún
Los huecos están en las mismas filas 3 y 4 que antes, pero ahora se ven. Ponga
missing_as="—" o missing_as="NA" y obtiene su propio marcador en los mismos lugares.
Cuántos huecos — variando la tasa
El problema. Usted quiere saber cómo se comporta el sistema con vacíos «raros» y con vacíos «frecuentes». Una sola tasa no se lo muestra.
La herramienta. Cambie solo missing y deje todo lo demás igual. X es un valor
presente, [] es un hueco. Tres columnas, 20 filas:
<env count="20" seed="demo">
<sequence name="A"><gen type="text" value="X" order="sequential" missing="0.1"/></sequence>
<sequence name="B"><gen type="text" value="X" order="sequential" missing="0.3"/></sequence>
<sequence name="C"><gen type="text" value="X" order="sequential" missing="0.6"/></sequence>
</env>
...
<data>0.1:[${{A}}] 0.3:[${{B}}] 0.6:[${{C}}]</data>
0.1:[X] 0.3:[X] 0.6:[] 0.1:[X] 0.3:[] 0.6:[X] 0.1:[X] 0.3:[X] 0.6:[X] 0.1:[X] 0.3:[] 0.6:[X] 0.1:[X] 0.3:[] 0.6:[] 0.1:[X] 0.3:[] 0.6:[X] 0.1:[X] 0.3:[X] 0.6:[] 0.1:[] 0.3:[X] 0.6:[] 0.1:[X] 0.3:[X] 0.6:[] 0.1:[X] 0.3:[X] 0.6:[X] 0.1:[] 0.3:[X] 0.6:[X] 0.1:[X] 0.3:[X] 0.6:[X] 0.1:[X] 0.3:[X] 0.6:[] 0.1:[X] 0.3:[X] 0.6:[] 0.1:[X] 0.3:[] 0.6:[] 0.1:[X] 0.3:[X] 0.6:[] 0.1:[X] 0.3:[X] 0.6:[X] 0.1:[X] 0.3:[X] 0.6:[X] 0.1:[X] 0.3:[X] 0.6:[] 0.1:[X] 0.3:[X] 0.6:[X]
Cuente los [] vacíos de cada columna: 0.1 → 2 huecos de 20, 0.3 → 5, 0.6 → 10.
Suba la tasa y los huecos se multiplican. La tasa × 20 daría 2 / 6 / 12, y solo la primera
columna cayó justo ahí: como cada valor se descarta de forma independiente, el conteo sobre
20 filas ronda la cifra esperada en vez de acertarla. Sobre 20 000 filas se acerca mucho
más.
Faltantes en varios campos
missing se combina con cualquier cosa: un rango simple, un
template, un patrón
regex, una distribución estadística. Aquí hay un registro
armado con tres campos: un nombre (sin vacíos), un teléfono (missing="0.3", marcador
N/A) y un ingreso (missing="0.25", con el marcador vacío por omisión):
<env count="8" seed="falta" local="es">
<sequence name="Name"> <gen type="template" value="person.male.firstName"/></sequence>
<sequence name="Phone"> <gen type="regex" value="\+52 55 [0-9]{4}-[0-9]{4}" missing="0.3" missing_as="N/A"/></sequence>
<sequence name="Income"> <gen type="number" value="30000..90000" missing="0.25"/></sequence>
</env>
...
<data>${{Name}} | phone: ${{Phone}} | income: ${{Income}}</data>
Gilberto | phone: +52 55 0799-7766 | income: Manuel | phone: N/A | income: 70687 Roberto | phone: N/A | income: 74842 Emiliano | phone: +52 55 3252-0924 | income: Ángel | phone: +52 55 6794-5318 | income: Ubaldo | phone: +52 55 5344-1029 | income: 55652 Cornelio | phone: +52 55 1697-4757 | income: 45147 Amado | phone: +52 55 5547-3053 | income: 47706
Las filas 2 y 3 traen N/A en el teléfono; las filas 1, 4 y 5 tienen el ingreso vacío (el
marcador por omisión no es nada en absoluto). Los vacíos de los dos campos son
independientes: un hueco en una columna no dice nada sobre la otra.
Qué filas pueden quedar vacías — missing_when
missing="p" por sí solo borra valores sin mirar nada más. Esa es una de las tres
formas en que los datos reales se pierden, y la más pobre: esos huecos no llevan
información, así que no enseñan nada ni se pueden predecir.
missing_when="…" añade las otras dos. Es una condición escrita en el mismo
lenguaje de expresiones que if=, y decide qué
filas son elegibles siquiera. missing="p" sigue decidiendo con qué frecuencia
una fila elegible se vacía de verdad.
| Lo que escribe | Cómo se llama | De dónde viene el hueco |
|---|---|---|
missing="0.2" | MCAR | de nada — todas las filas son igual de probables |
missing="0.8" missing_when="Age < 30" | MAR | de otra columna que aún se ve |
missing="0.8" missing_when="_value > 60000" | MNAR | del valor mismo, que ya no está |
Los nombres importan porque deciden qué se le puede exigir a un modelo entrenado con el archivo. Los huecos MCAR no enseñan nada. Los MAR se predicen desde lo que queda en la fila — una imputación tiene de dónde agarrarse. Los MNAR solo se predicen desde lo que se quitó: el caso difícil, y en el que su tubería tiene más probabilidades de equivocarse.
MAR — el hueco depende de otra columna
<sequence name="Age"><gen type="number" value="18..70"/></sequence>
<sequence name="Income">
<gen type="number" value="30000..90000" missing="0.8" missing_as="NULL" missing_when="Age < 30"/>
</sequence>
age: 66 | income: 33520 age: 56 | income: 76606 age: 28 | income: NULL age: 26 | income: NULL age: 67 | income: 40610 age: 33 | income: 86092 age: 68 | income: 86789 age: 18 | income: NULL
Cada vacío cae en una fila de menos de 30 años; nadie mayor perdió su ingreso.
Age se lee exactamente como la leería if="Age < 30", así que valen las mismas
reglas: la columna debe declararse arriba de la que la nombra.
MNAR — el hueco depende del valor que ya no está
Dentro de missing_when, _value es el valor que este generador produjo para la
fila: justo lo que el vacío habría escondido. Es un nombre que da el lenguaje,
como _count y _last; ninguna configuración lo declara.
<sequence name="Income">
<gen type="number" value="30000..90000" missing="0.8" missing_as="NULL" missing_when="_value > 60000"/>
</sequence>
income: NULL income: 53006 income: 52544 income: NULL income: 52481 income: NULL income: NULL income: 35921
Todos los ingresos que sobreviven están por debajo de 60 000. Los que ganan más son los que no contestaron — que es exactamente el sesgo que MNAR nombra, y exactamente lo que un modelo entrenado con las filas visibles no puede ver.
_value es el valor después de anomaly=, porque ese es el
valor que la fila habría llevado. Así que missing_when="_value > 150000" junto a
un anomaly= vacía justamente los picos, y la columna anomaly_flag está de
acuerdo: una celda vaciada ya no tiene pico que etiquetar.
La letra pequeña
- La tasa sigue haciendo falta.
missing_whensinmissingno decide nada, y se rechaza en vez de ignorarse. - Una palabra suelta es un literal, aquí como en todo el lenguaje:
missing_when="Tier == hi"compara con la palabrahi. Un nombre de columna mal escrito se reporta (TDC215) en vez de leerse en silencio como palabra. - No junto con
repeat=. Una celda repetida guarda varios valores en una fila y la condición pregunta por uno; en vez de adivinar qué lectura quería, la combinación se rechaza. - Los dos motores. La condición se evalúa por fila con el mismo lector de columnas que usan ambos motores, así que una corrida en streaming y otra en memoria producen el mismo archivo.
Detalles
- Determinista. El mismo
seedproduce los mismos vacíos — vea Determinismo y proporciones. Un dataset «agujerado» se reproduce byte por byte, corrida tras corrida. - Los dos motores, cualquier volumen. Los vacíos se deciden por número de fila, así que la memoria no crece con el dataset — vea Salidas grandes y streaming.
missing="0"significa que no hay ningún vacío — exactamente como si el atributo no estuviera.
Vea también
- Secuencias — las columnas a las que les está
haciendo huecos, y cómo
${{Name}}las lee. - Text y Number — los generadores usados en los ejemplos de arriba.
- Máscaras y mayúsculas —
order="sequential"y los demás atributos transversales de los generadores.