Skip to contents

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 perfil creado por perfilar().

datos

data.frame, tibble o data.table sobre 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_limpieza o 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 TRUE de 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;amp;— queda en &amp;, 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 &amp;: 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