planificar_limpieza() transforma los hallazgos de un objeto perfil en un
objeto de datos editable, sin modificar los datos examinados. Cada fila
representa una acción propuesta. Sólo se marcan como recomendadas las
estrategias correctas con independencia del dominio; algunas, como marcar
valores extremos, permanecen inactivas hasta que se decida actuar. Las
decisiones contextuales quedan desactivadas y los formatos de fecha ambiguos
quedan bloqueados.
Usage
planificar_limpieza(perfil, datos = NULL, soporte_minimo_dependencia = 2L)
aplicar(plan, datos, permitir_eliminacion = FALSE, conservar_eliminados = TRUE)Arguments
- perfil
Objeto de clase
perfilcreado porperfilar().- datos
data.frame,tibbleodata.tablesobre el que se ejecuta el plan. El objeto recibido no se modifica.- soporte_minimo_dependencia
Cantidad mínima de observaciones concordantes por valor determinante para proponer una imputación.
- plan
Objeto de clase
plan_limpiezao data frame con el mismo contrato. Puede filtrarse y editarse antes de aplicarlo.- permitir_eliminacion
Segundo consentimiento obligatorio para ejecutar acciones que eliminan filas o columnas. Sin él, una acción eliminatoria seleccionada hace que
aplicar()se niegue antes de tocar nada: no se ejecuta ninguna acción del plan —tampoco las que no eliminan— y no hay registro, porque no hubo ejecución. El error nombra las acciones y los dos caminos: dar el consentimiento, o desactivarlas y aplicar el resto.- conservar_eliminados
Si se conservan en el resultado las filas y columnas retiradas. Es
TRUEde forma predeterminada.
Value
planificar_limpieza() devuelve un data frame de clase
plan_limpieza. aplicar() devuelve una lista de clase
resultado_limpieza con datos, registro, plan_aplicado, el plan
sincronizado y eliminados. El registro conserva estado (ejecutada
o fallida), error, n_no_reversibles y la justificacion de cada
acción seleccionada, incluso cuando una falla y las siguientes continúan.
n_codificacion_normalizada cuenta, por acción, las celdas cuya marca de
codificación cambió: es el caso de una acción de texto sobre celdas
latin1, cuyo valor se conserva y cuyos bytes no.
n_no_reversibles cuenta las celdas cuyo VALOR se perdió y no se puede
recuperar desde el resultado: un centinela -999 que pasa a ausencia, un
extremo recortado a su límite, un marcador de ausencia convertido, o un
número que se redondeó al convertirlo. Las acciones que normalizan la
escritura —recortar espacios, quitar un invisible de transporte,
reemplazar separadores o cambiar mayúsculas— dejan el valor en su lugar y
no cuentan, salvo cuando la normalización fusiona valores que eran
distintos: ahí lo que los separaba no queda en ningún lado y esas celdas
sí se cuentan. El criterio se mide sobre el resultado, no por el nombre de
la acción: quitar un guion suave de PRO<U+00AD>DUCTO-A no pierde nada,
y quitar un espacio de ancho cero que distinguía dos claves fusiona las
dos.
Si una acción seleccionada no produce ningún efecto, se registra como
fallida con el motivo y su copia no se incorpora al resultado. La
comprobación del efecto observa n_cambiadas aunque n_afectadas sea
NA o haya sido editado: una acción seleccionada que no cambia nada queda
fallida, porque la ausencia de efecto es observable sin depender de la
estimación.
Si una columna de entrada es un factor, las acciones que transforman su
texto devuelven una columna character: no se reconstruyen los niveles
originales, porque una limpieza puede introducir valores nuevos.
Details
aplicar() ejecuta exclusivamente las filas con aplicar == TRUE, sobre una
copia de datos. Verifica que cada columna siga siendo identificable y que
las conversiones sean completas antes de sustituirla. Devuelve los datos
nuevos junto con un registro de las acciones y sus parámetros. El mismo
registro queda en el atributo registro_limpieza de los datos resultantes.
Las alternativas para un mismo hallazgo comparten grupo; las acciones
independientes usan NA. Como máximo una alternativa de cada grupo puede
tener aplicar == TRUE, invariante que aplicar() vuelve a validar. No se
agrega una fila ficticia para "no hacer nada": decision_grupo distingue
pendiente, recomendada, desactivada, elegida y omitida, mientras
recomendacion_grupo = "no_hacer_nada" representa una recomendación
explícita de conservar los datos. Esto permite separar un grupo aún no
revisado de una omisión deliberada.
estado distingue acciones lista, bloqueada e informativa; orden
fija la secuencia reproducible. Si dos acciones comparten el mismo orden,
el empate lo resuelve id_accion, no la posición de la fila: reordenar el
plan no cambia el resultado. Y un grupo marcado como elegida sin ninguna
acción activa se rechaza, porque no es ni una elección ni una omisión. n_afectadas es la estimación del perfil
sobre lo que esta acción tocaría, que puede ser menos que el conteo del
hallazgo que la originó cuando la acción sólo cubre parte del caso: una
columna con tres valores de codificación rota, de los cuales uno es
reparable, produce un hallazgo con n_afectados = 3 y una acción
reparar_codificacion con n_afectadas = 1. Las dos cifras son ciertas y
cuentan cosas distintas. unidad_conteo dice si cuenta filas, columnas o
valores distintos —lo
declara la acción cuando cuenta en una unidad propia, y sólo si no lo hace se
hereda del hallazgo—. El registro informa n_cambiadas sobre los datos
recibidos.
n_afectadas y n_cambiadas pueden no coincidir, y las dos son ciertas.
La estimación se calcula sobre los datos que se perfilaron; el registro
cuenta lo que pasó al aplicar. Si una acción anterior del mismo plan ya tocó
esa columna, la posterior encuentra menos —o más— de lo estimado: con
convertir_sentinelas_numericos (orden 110) convirtiendo tres -999 en
ausentes, winsorizar_outliers (orden 520) recorta dos valores donde el plan
estimaba siete. No es un desvío que ocultar: orden, n_afectadas y
n_cambiadas se publican los tres, y compararlos es la forma de ver el
efecto de la composición. Sólo el caso extremo —la acción no produce ningún
efecto —también cuando el plan no trae una estimación válida— se registra
como fallida con su motivo.
Esa comparación sólo lee composición cuando las dos cifras cuentan en la
misma unidad. n_afectadas cuenta en la unidad_conteo que el plan
declara y n_cambiadas cuenta lo que la acción tocó al aplicarse, que es
su unidad natural. Cuando la acción declara unidad_conteo = "valor_distinto" —las conversiones de mayúsculas y minúsculas—, las dos
cifras miden poblaciones distintas y su diferencia no dice nada sobre la
composición: medido sobre c("Ana", "ana", "ANA", "Beto", " Ana "),
convertir_minusculas estima n_afectadas = 3 valores distintos y el
registro publica n_cambiadas = 4 celdas. Las dos son ciertas. La unidad
del plan se recupera uniendo el registro con el plan por id_accion, que
los dos publican. reversible
indica si la conversión conserva la identidad de cada valor. Las
conversiones se comprueban sobre todos los valores de datos: las numéricas
bloquean ceros iniciales, colisiones no inyectivas y valores con más cifras
significativas de las que guarda un número de doble precisión —un decimal se
compara con la precisión con que vino escrito—, mientras que fechas,
fechas-hora y lógicos sólo bloquean conversiones no ejecutables o no
inyectivas. Las fechas pueden cambiar a la representación canónica del tipo
sin que eso sea una pérdida. Sin datos no se puede hacer la comprobación y
la acción queda bloqueada. Cuando una conversión de tipo se ejecuta y no
es reversible se marca destructiva —también si la columna no era segura y
se activa a mano—, no se activa por defecto y el registro conserva
n_no_reversibles y la justificación de la decisión.
destructiva no es sinónimo de "pierde algo": marca las acciones que el
usuario tiene que activar a mano —las que retiran filas o columnas y las
conversiones que pierden representación, como winsorizar_outliers sobre una
columna guardada como entera, donde los límites de Tukey son cuartiles y
la columna queda en doble precisión: la justificación lo dice y parametros
publica tipo_original y tipo_resultante. Sobre cualquier otra clase
—texto con números, factor, fecha— la acción conserva la clase y reescribe
sólo las celdas recortadas; Inf, NaN y NA quedan como estaban— y por
eso ninguna acción
destructiva puede estar recomendada. Hay acciones recomendadas que sí
pierden el valor de una celda: convertir_ausencias_textuales cambia un
marcador por NA y eliminar_controles_invisibles quita un carácter. Esas
lo dicen en su justificación y el registro las cuantifica en
n_no_reversibles; leer destructiva = FALSE no significa que no se haya
perdido nada, sino que el paquete pudo recomendar la acción sin conocer el
dominio.
Sobre una columna factor las acciones por celda devuelven texto: el
resultado no puede ser un factor incompleto, así que el orden declarado y los
niveles sin observaciones no se conservan. La justificación de la acción lo
dice, y si el factor es ordenado la acción queda recomendada pero sin
activar, porque conservar el orden es una decisión del dominio.
Tres atributos del plan declaran lo que el plan no cubre.
cobertura_diagnosticos trae los diagnósticos que el perfil no pudo
evaluar, para que leer tres acciones no se confunda con "lo demás está
bien". hallazgos_sin_accion_por_columna_ambigua trae los hallazgos medidos
que no produjeron acción porque su columna comparte nombre con otra y no hay
forma de saber sobre cuál actuaría la limpieza; el remedio es normalizar los
nombres y volver a perfilar. hallazgos_sin_accion trae el resto: los
hallazgos que el perfil midió, con su columna identificada, y que ninguna
acción del plan atiende —porque el plan no tiene una estrategia para ese
tipo, o porque la que tiene necesitaba una condición que no se cumplió—. Su
motivo dice si la misma columna recibió otras acciones, sin afirmar que
alguna cubra el hallazgo: eso es una decisión del dominio. Los tres se
imprimen con el plan.
convertir_numero_regional sólo se recomienda si todos los valores
presentes comparten convención decimal, unidad y moneda. Un valor con %
se divide por 100 y queda como proporción en [0, 1], la escala con que el
paquete publica toda proporción; una unidad o un símbolo de moneda dejan de
formar parte del valor y quedan en parametros. La justificación lo dice
cuando ocurre. Una columna que mezcla 5 con 5 % no se convierte: habría
que decidir si el número sin % está en la misma escala.
La acción de codificación prueba las tablas congeladas de varias
codificaciones y deja en estado_reparacion uno de reparado,
reparado_parcialmente o no_se_pudo. Una reparación parcial no se activa
automáticamente: debe revisarse y seleccionarse de forma explícita. La
estrategia se llama reparar_codificacion y no limita el motor a latin-1.
Unos mismos bytes pueden recibir dos diagnósticos: c2 80 es a la vez un
carácter de control C1 y la huella de un € de Windows-1252 leído como
latin-1. Cuando el plan propone reparar la codificación y eliminar ese
control, manda la reparación —corre primero y restituye el €—, y la
eliminación queda sin nada que hacer. Es la lectura habitual en texto real;
en el caso raro de un control C1 genuino, la reparación lo convierte en €.
Una celda cuyo texto no se puede leer —declarada bytes con bytes que no
son UTF-8, o sin marca en una sesión UTF-8, que es lo que deja read.csv()
sin fileEncoding sobre un archivo latin1— no se transforma: el perfil no la
midió y la informa como codificacion_invalida, cuyo remedio es volver a leer
la fuente declarando su codificación. Las acciones de texto trabajan sobre las
demás celdas de la columna y cuentan sólo lo que cambiaron.
Una celda latin1 sí se transforma —ahí R conoce la codificación y la
convierte sin pérdida—, y el resultado queda marcado UTF-8. Como la acción
toca sólo las celdas que cambia, una columna latin1 puede quedar con marcas
mixtas: las celdas transformadas en UTF-8 y las intactas en latin1. El
valor es el mismo, pero los bytes no, así que el registro lo cuenta en
n_codificacion_normalizada en vez de dejarlo implícito. No se convierte la
columna entera a propósito: eso tocaría celdas que el plan no declaró como
cambiadas y haría mentir a n_cambiadas por el otro lado.
Si se marca una acción que no está lista, aplicar() aborta antes de
modificar la copia y enumera las filas problemáticas. Una acción que sí está
lista pero falla se registra con su error y no impide aplicar las siguientes:
cada una conserva atomicidad sobre su propia columna o tabla. Las acciones
que efectivamente eliminan filas o columnas requieren además
permitir_eliminacion = TRUE; una conversión destructiva requiere selección
explícita y deja la pérdida cuantificada. Por defecto, el resultado conserva
lo retirado en eliminados; use conservar_eliminados = FALSE para evitar
ese costo de memoria.
Los hallazgos controles_invisibles, entidades_html y separadores_en_campo
tienen acciones separadas. La detección de invisibles informa tanto los
caracteres que se pueden normalizar como los ZWJ/ZWNJ significativos; la
normalización actúa sobre un conjunto más pequeño que la detección. La acción
eliminar_controles_invisibles quita controles C0/C1 que no son separadores
y los invisibles Unicode de transporte, y se recomienda por defecto; conserva
ZWJ/ZWNJ. normalizar_espacios_invisibles colapsa espacios Unicode (incluido
NBSP) a un espacio ASCII y, como su hermana, se recomienda y se activa por
defecto: queda un espacio, así que el valor sigue ahí; si al colapsarlo dos
valores que eran distintos quedan iguales, el registro lo cuenta en
n_no_reversibles. decodificar_entidades_html cubre las entidades
con nombre comunes en español y referencias numéricas válidas, pero no se
activa sola porque un ampersand puede ser contenido legítimo. Decodifica
una capa: un texto codificado dos veces —&amp;— queda en &,
y el perfil del resultado lo vuelve a señalar. No se itera hasta el fondo
porque no se puede distinguir una doble codificación de un texto que quería
decir &: la segunda capa se decide viéndola.
reemplazar_separadores convierte tabulaciones, saltos de línea, avances de
página y tabulaciones verticales (\\t, \\n, \\r, \\r\\n, \\f y \\v)
en un espacio y también requiere una decisión explícita. Las tres acciones
registran el número de valores cambiados. Una comparación aproximada con
normalizar = TRUE usa estas mismas clases: colapsa espacios y omite basura
de transporte, pero conserva ZWJ/ZWNJ.
Las imputaciones por dependencia funcional se ofrecen desactivadas. Aunque una dependencia exacta permite deducir un valor sin usar media, moda o un modelo externo, sigue siendo una regularidad aprendida de una sola entrega y puede reflejar un error sistemático en vez de una regla de negocio. El plan conserva el mapa y su soporte para que el usuario la confirme; sólo entonces se aplica y se vuelve a validar contra los datos recibidos. Si la protección enmascaró alguna clave del mapa, éste no se usa como tabla de cruce: la relación se reconstruye sobre los datos recibidos con el soporte declarado, sin publicar sus valores.
marcar_filas_duplicadas añade dos columnas. .fila_duplicada reproduce la
semántica de duplicated() y marca sólo las apariciones posteriores;
.grupo_duplicado identifica a todas las filas que participan en cada
grupo de contenido idéntico. Marcar no elimina filas: con las dos columnas
incluidas, un perfil posterior tampoco vuelve a contar esas filas como
duplicadas exactas, porque las marcas las distinguen. Para saber si los
duplicados siguen en la tabla hay que quitar las columnas de marca antes de
perfilarla.
El orden operativo se aparta deliberadamente de la secuencia dimensional
frescura–completitud–exactitud–consistencia–unicidad sugerida por el marco.
Primero marca duplicados sin borrar, luego normaliza ausencias y texto, y
deja los cambios de esquema para el final. Esto evita perder la evidencia
original, permite imputar antes de convertir tipos y mantiene identificables
las columnas durante todo el plan. Las eliminaciones nunca se activan por
defecto, por lo que deduplicar temprano no puede hacer desaparecer registros.
destructiva también marca una conversión que pierde representación, aunque
no elimine filas o columnas. El consentimiento permitir_eliminacion sólo
se exige para las estrategias que efectivamente retiran filas o columnas;
una conversión destructiva requiere que el usuario la active explícitamente
y deja su pérdida cuantificada en el registro.
Marcar o eliminar ausentes va después de normalizarlos, no antes. Una
columna con "N/A" y "sin dato" tiene ausentes disfrazados que
convertir_ausencias_textuales convierte en NA reales; si la marca
corriera primero, quedaría una columna .ausente_x que dice FALSE en
filas que terminan en NA —una afirmación falsa sobre los datos, publicada
con las dos acciones en ejecutada y sin error—. Medido sobre siete formas
de tabla antes de corregirlo, tres producían esa marca falsa siguiendo el
idioma documentado plan$aplicar <- plan$recomendada. Por la misma razón,
eliminar_filas_ausentes también va después: eliminar antes deja sin
eliminar las filas cuyo ausente todavía estaba disfrazado.
Examples
datos <- data.frame(categoria = c(" A", "S/D", "B"))
perfil <- perfilar(datos)
plan <- planificar_limpieza(perfil, datos)
plan[, c("grupo", "estrategia", "recomendada", "aplicar")]
#> grupo estrategia recomendada aplicar
#> 1 <NA> convertir_ausencias_textuales TRUE TRUE
#> 2 <NA> recortar_espacios TRUE TRUE
resultado <- aplicar(plan, datos)
resultado$datos
#> categoria
#> 1 A
#> 2 <NA>
#> 3 B
