diff --git a/locale/es/clean-data.Rmd b/locale/es/clean-data.Rmd new file mode 100644 index 00000000..895f3f15 --- /dev/null +++ b/locale/es/clean-data.Rmd @@ -0,0 +1,646 @@ +--- +title: Datos de casos limpios +teaching: 20 +exercises: 10 +--- + +:::::::::::::::::::::::::::::::::::::: preguntas + +- ¿Cómo limpiar y normalizar los datos de los casos? + :::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objetivos + +- Explicar cómo limpiar, curar y normalizar los datos de casos utilizando `{cleanepi}` paquete +- Realizar las operaciones esenciales de limpieza de datos que deben efectuarse en un conjunto de datos de casos sin procesar. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::: prerrequisito + +Este episodio requiere: + +- Descargar el archivo [ébola\_simulada\_2.csv](https://epiverse-trace.github.io/tutorials-early/data/simulated_ebola_2.csv) +- Guárdalo en la carpeta `data/`. + +::::::::::::::::::::: + +## Introducción + +En el proceso de análisis de datos sobre brotes es esencial asegurarse de que el conjunto de datos está limpio, curado, estandarizado +y válido para facilitar un análisis preciso y reproducible. +Este episodio se centra en la limpieza de los datos de epidemias y brotes epidémicos mediante el paquete +[cleanepi](https://epiverse-trace.github.io/cleanepi/), +A efectos de demostración, trabajaremos con un conjunto de datos simulado de casos de ébola. + +Empecemos cargando el paquete `{rio}` para leer los datos y el paquete `{cleanepi}` +para limpiarlos. Utilizaremos el _pipe_ `%>%` para conectar algunas de sus funciones e incluir otras del paquete `{dplyr}` así que vamos a llamar también al paquete `{tidyverse}`: + +```{r, eval=TRUE, message=FALSE, warning=FALSE} +# Cargar paquetes +library(tidyverse) # para poder usar las funciones de {dplyr} y el pipe %>% +library(rio) # para importar los datos +library(here) # para referencia sencilla de archivos +library(cleanepi) +``` + +::::::::::::::::::: lista de comprobación + +### Doble dos puntos + +El doble dos punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza la función `filter()` del paquete `{dplyr}`. + +Esto nos ayuda a recordar las funciones del paquete y a evitar conflictos de espacio de nombres. + +::::::::::::::::::: + +El primer paso es importar el conjunto de datos al entorno de trabajo, lo que puede hacerse siguiendo las directrices +descritas en el episodio [Leer datos del caso](../episodes/read-cases.Rmd). Esto implica cargar +el conjunto de datos en el entorno de `R` y ver su estructura y contenido. + +```{r, eval=FALSE, echo=TRUE, message=FALSE} +# Leer los datos +# ej.: si el camino al archivo es data/simulated_ebola_2.csv entonces: +raw_ebola_data <- rio::import( + here::here("data", "simulated_ebola_2.csv") +) %>% + dplyr::as_tibble() # para una salida sencilla del conjunto de datos +``` + +```{r, eval=TRUE, echo=FALSE, message=FALSE} +# Leer los datos +raw_ebola_data <- rio::import( + file.path("data", "simulated_ebola_2.csv") +) %>% + dplyr::as_tibble() # para una salida sencilla del conjunto de datos +``` + +```{r, message=FALSE} +# Muestra el conjunto de datos +raw_ebola_data +``` + +::::::::::::::::: debate + +Vamos a **diagnosticar** el conjunto de datos. Enumera todas las características del conjunto de datos anterior que son problemáticas para el análisis de datos. + +¿Alguna de esas características te resulta familiar de algún análisis de datos anterior que hayas realizado? + +:::::::::::::::::::::::::::: + +::::::::::::::::::: instructor + +Falicita un debate breve para relacionar la característica diagnosticada con las operaciones de limpieza necesarias. + +Puedes utilizar estos términos para **diagnosticar características**: + +- *Codificación*, como entradas de sexo y edad utilizando números, letras y palabras. También fechas en diferente disposición y formatos + ("dd/mm/aaaa" o "aaaa/mm/dd"). Menos visibles, pero también los nombres de las columnas. +- *Datos Faltantes* ¿cómo interpretar una entrada como "" en estado o "-99" en otra columna? ¿tenemos un diccionario de datos de + el proceso de recolección de datos? +- *Inconsistencias* como tener una fecha de muestra anterior a la fecha de inicio. +- *Valores no posibles* como observaciones atípicas con fechas fuera de un marco temporal previsto. +- *Duplicados* ¿todas las observaciones son únicas? + +Puedes utilizar estos términos para referirte a **operaciones de limpieza**: + +- Normalizar el nombre de la columna +- Normalizar variables categóricas como sexo/género +- Normalizar columnas de fechas +- Convertir de valores de caracteres a valores numéricos +- Comprobar la secuencia de eventos con fechas + +:::::::::::::::::::::::::::::: + +## Una inspección rápida + +La exploración e inspección rápidas del conjunto de datos son cruciales antes de sumergirse en cualquier tarea de análisis. `{cleanepi}` simplifica este proceso con la función `scan_data()`. Veamos cómo puedes utilizarla: + +```{r} +cleanepi::scan_data(raw_ebola_data) +``` + +Los resultados ofrecen una visión general del contenido de cada columna, incluidos los nombres de las columnas y el porcentaje de algunos datos y los tipos de datos por columna. +Puedes ver que los nombres de las columnas del conjunto de datos son descriptivos pero carecen de coherencia, ya que algunas están compuestas por +varias palabras separadas por espacios en blanco. Además, algunas columnas contienen más de un tipo de datos, y hay +valores perdidos en otras. + +## Operaciones habituales + +En esta sección se muestra cómo realizar algunas operaciones comunes de limpieza de datos utilizando la función `{cleanepi}` paquete. + +### Normalizar los nombres de las columnas + +Para este conjunto de datos de ejemplo, normalizar los nombres de las columnas suele implicar eliminar espacios y conectar palabras diferentes +con "\_". Esta práctica ayuda a mantener la coherencia y la legibilidad del conjunto de datos. Sin embargo, la función utilizada para +normalizar los nombres de las columnas ofrece más opciones. Escribe `?cleanepi::standardize_column_names` para más detalles. + +```{r} +sim_ebola_data <- cleanepi::standardize_column_names(raw_ebola_data) +names(sim_ebola_data) +``` + +Si quieres mantener ciertos nombres de columna sin someterlos al proceso de normalización, puedes utilizar el argumento `keep` de la función `cleanepi::standardize_column_names()`. Este argumento acepta un vector de nombres de columnas +que deben mantenerse sin cambios. + +::::::::::::::::::::::::::::::::::::: desafío + +- ¿Qué diferencias puedes observar en los nombres de las columnas? + +- Normaliza los nombres de las columnas del conjunto de datos de entrada, pero mantén los nombres de la primera columna tal cual está. + +::::::::::::::::: sugerencia + +Puedes probar `cleanepi::standardize_column_names(data = raw_ebola_data, keep = "V1")` + +:::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::: + +### Eliminar irregularidades + +Los datos brutos pueden contener irregularidades como filas **duplicadas**, filas y columnas **vacías**, o columnas **constantes** +(donde todas las entradas tienen el mismo valor.) Funciones de `{cleanepi}` como `remove_duplicates()` y `remove_constants()` +eliminar esas irregularidades, como se demuestra en el código siguiente. + +```{r} +# Remueve constantes +sim_ebola_data <- cleanepi::remove_constants(sim_ebola_data) +``` + +Ahora, ¡imprime la salida para identificar qué columna constante has eliminado! + +```{r} +# Remueve duplicados +sim_ebola_data <- cleanepi::remove_duplicates(sim_ebola_data) +``` + + + +::::::::::::::::::::: spoiler + +#### ¿Cuántas filas has eliminado? ¿Qué filas has eliminado? + +Puedes obtener el número y la ubicación de las filas duplicadas que se encontraron. Ejecuta `cleanepi::print_report()`, +espera a que se abra el informe en tu navegador, y busca la pestaña "Duplicados". + +```{r, eval=FALSE, echo=TRUE} +# Print a report +cleanepi::print_report(sim_ebola_data) +``` + +::::::::::::::::::::: + +::::::::::::::::::::: desafío + +En el siguiente conjunto de datos: + +```{r, echo=FALSE, eval=TRUE} +library(tidyverse) + +#crea conjunto de datos +df <- tibble( + col1 = c(1, 2), + col2 = c(1, 3) +) %>% + mutate(col3 = rep("a", nrow(.))) %>% + mutate(col4 = rep("b", nrow(.))) %>% + mutate(col5 = rep(NA_Date_, nrow(.))) %>% + add_row(col1 = NA_integer_, col3 = "a") %>% + add_row(col1 = NA_integer_, col3 = "a") %>% + add_row(col1 = NA_integer_, col3 = "a") %>% + add_row(col1 = NA_integer_) + +df +``` + +Qué columnas o filas son: + +- ¿Duplicadas? +- ¿Vacía? +- ¿Constante? + +::::::::::::::: pista + +Duplicados se refiere sobre todo a filas repetidas. Las filas o columnas vacías pueden ser un subconjunto dentro del conjunto de filas constantes o columnas. + +::::::::::::::: + +::::::::::::::::::::: + +::::::::::::::: instructor + +- filas duplicadas: 3, 4, 5 +- filas vacías: 6 +- columnas vacías: 5 +- filas constantes: 6 +- columnas constantes: 5 + +Haz notar a tus estudiantes que el usuario puede crear nuevas columnas o filas constantes tras eliminar algunas. + +```{r} +df %>% + cleanepi::remove_constants() + +df %>% + cleanepi::remove_constants() %>% + cleanepi::remove_constants() +``` + +::::::::::::::: + +### Sustitución de valores perdidos + +Además de las irregularidades, los datos brutos pueden contener valores perdidos que pueden estar codificados por diferentes cadenas, +incluidas las vacías. Para garantizar un análisis sólido, es una buena práctica es sustituir todos los valores perdidos por `NA` en el +conjunto de datos completo. A continuación se muestra un fragmento de código que demuestra cómo puedes conseguirlo en `{cleanepi}`: + +```{r} +sim_ebola_data <- cleanepi::replace_missing_values( + data = sim_ebola_data, + na_strings = "" +) + +sim_ebola_data +``` + +¡ + +### Validar los ID de los sujetos + +Cada entrada del conjunto de datos representa a un sujeto y debe distinguirse por una columna específica formateada en un formato +particular, como estar dentro de un intervalo especificado, contener determinados prefijos y/o sufijos, contener un +determinado número de caracteres. La dirección `{cleanepi}` ofrece la función `check_subject_ids()` diseñada con precisión +para esta tarea, como se muestra en el siguiente fragmento de código. Esta función valida si son únicos y cumplen los requisitos +requeridos. + +```{r} +sim_ebola_data <- + cleanepi::check_subject_ids( + data = sim_ebola_data, + target_columns = "case_id", + range = c(0, 15000) + ) +``` + +Ten en cuenta que nuestro conjunto de datos simulado contiene IDS de sujetos duplicados. + +::::::::::::::::: spoiler + +#### ¿Cómo corregir las identificaciones de los sujetos? + +Imprimamos un informe preliminar con `cleanepi::print_report(sim_ebola_data)`. Céntrate en los "Id. de asunto inesperados". +para identificar qué identificaciones requieren un tratamiento adicional. + +Después de terminar este tutorial, te invitamos a explorar la guía de referencia de paquetes de `{cleanepi}` para encontrar el +función que puede solucionar esta situación. + +::::::::::::::::::::::::: + +### Normalización de fechas + +Ciertamente, un conjunto de datos sobre epidemias contiene columnas de fechas para distintos acontecimientos, como la fecha de infección, +fecha de inicio de los síntomas, etc. Estas fechas pueden tener distintos formatos, y es una buena práctica normalizarlas. +La página `{cleanepi}` proporciona funciones para convertir las columnas de fecha de los conjuntos de datos sobre epidemias al formato ISO, +garantizando la coherencia entre las distintas columnas de fecha. A continuación te mostramos cómo puedes utilizarlo en nuestro conjunto de datos simulado: + +```{r} +sim_ebola_data <- cleanepi::standardize_dates( + sim_ebola_data, + target_columns = c( + "date_onset", + "date_sample" + ) +) + +sim_ebola_data +``` + +Esta función convierte los valores de las columnas de destino, o averiguará automáticamente las columnas de fecha dentro de +del conjunto de datos (si `target_columns = NULL`) y las convertirá en **Ymd** . + +::::::::::::::::::: debate + +#### ¿Cómo es posible? + +¡Te invitamos a que encuentres el paquete de claves que funciona internamente leyendo la sección Detalles del +[Manual de referencia de las variables de fecha normalizadas](https://epiverse-trace.github.io/cleanepi/reference/standardize_dates.html#details)! + +::::::::::::::::::: + +### Convertir a valores numéricos + +En el conjunto de datos sin procesar, algunas columnas pueden contener una mezcla de valores numéricos y de caracteres. Querrás convertir los valores de caracteres explícitamente en numéricos. Por ejemplo, en nuestro conjunto de datos simulado, en la columna edad algunas entradas están +escritas con palabras. En `{cleanepi}` la función `convert_to_numeric()` realiza dicha conversión como se ilustra a continuación en el código. + +```{r} +sim_ebola_data <- cleanepi::convert_to_numeric(sim_ebola_data, + target_columns = "age" +) + +sim_ebola_data +``` + +::::::::::::::::: llamada + +### Soporte para varios idiomas + +Gracias al `{numberize}` paquete, podemos convertir números escritos como palabras en inglés, francés o español a ¡números enteros positivos! + +::::::::::::::::::::::::: + +## Operaciones relacionadas con la epidemiología + +Además de las tareas habituales de limpieza de datos, como las comentadas en la sección anterior, el paquete `{cleanepi}` ofrece +funcionalidades adicionales adaptadas específicamente para procesar y analizar datos de brotes y epidemias. Esta sección +cubre algunas de estas tareas especializadas. + +### Comprobación de la secuencia de eventos con fechas + +Garantizar el orden y la secuencia correctos de los eventos con fechas es crucial en el análisis de datos epidemiológicos, especialmente +cuando se analizan enfermedades infecciosas, en las que la cronología de acontecimientos como la aparición de síntomas y la recolección de muestras es esencial. +El sitio `{cleanepi}` proporciona una útil función llamada `check_date_sequence()` precisamente para este fin. + +Aquí tienes un fragmento de código de ejemplo que demuestra el uso de la función `check_date_sequence()` en nuestro conjunto de datos simulados sobre el ébola + +```{r, warning=FALSE} +sim_ebola_data <- cleanepi::check_date_sequence( + data = sim_ebola_data, + target_columns = c("date_onset", "date_sample") +) +``` + +Esta función es crucial para garantizar la integridad y precisión de los datos en los análisis epidemiológicos, ya que ayuda a identificar +cualquier incoherencia o error en el orden cronológico de los acontecimientos, permitiéndote abordarlos adecuadamente. + +::::::::::::::::: spoiler + +#### ¿Cuáles son las secuencias de fechas incorrectas? + +Imprimamos otro informe preliminar con `cleanepi::print_report(sim_ebola_data)`. Concéntrate en +"Secuencia de fechas incorrecta" para identificar qué IDs tenían este problema. + +::::::::::::::::::::::::: + +### Sustitución basada en diccionario + +En el ámbito del preprocesamiento de datos, es frecuente encontrarse con situaciones en las que determinadas columnas de un conjunto de datos, +como la columna "sexo" de nuestro conjunto de datos simulado sobre el ébola, se espera que tengan valores o factores específicos. +Sin embargo, también es habitual que aparezcan valores inesperados o erróneos en estas columnas, que deben sustituirse por +valores adecuados. En `{cleanepi}` ofrece soporte para la sustitución basada en diccionario, un método que te permite +sustituir valores en columnas concretas basándote en las correspondencias definidas en un diccionario. +Este enfoque garantiza la coherencia y la precisión en la limpieza de datos. + +Además, `{cleanepi}` proporciona un diccionario incorporado adaptado específicamente a los datos epidemiológicos. El ejemplo +de abajo incluye correspondencias para la columna "sexo". + +```{r} +test_dict <- base::readRDS( + system.file("extdata", "test_dict.RDS", package = "cleanepi") +) %>% + dplyr::as_tibble() # para una salida simple del conjunto de datos + +test_dict +``` + +Ahora podemos utilizar este diccionario para normalizar los valores de la columna "sexo" según categorías predefinidas. +A continuación se muestra un fragmento de código de ejemplo que demuestra cómo utilizar esta funcionalidad: + +```{r} +sim_ebola_data <- cleanepi::clean_using_dictionary( + sim_ebola_data, + dictionary = test_dict +) + +sim_ebola_data +``` + +Este enfoque simplifica el proceso de limpieza de datos, garantizando que los datos categóricos de los conjuntos de datos epidemiológicos sean +categorizados con precisión y listos para su posterior análisis. + +:::::::::::::::::::::::::: spoiler + +#### ¿Cómo crear tu propio diccionario de datos? + +Ten en cuenta que, cuando la columna del conjunto de datos contiene valores que no están en el diccionario, la función +`cleanepi::clean_using_dictionary()` provocará un error. + +Puedes iniciar un diccionario personalizado con un conjunto de datos dentro o fuera de R. Puedes utilizar la función +`cleanepi::add_to_dictionary()` para incluir nuevos elementos en el diccionario. Por ejemplo + +```{r} +new_dictionary <- tibble::tibble( + options = "0", + values = "female", + grp = "sex", + orders = 1L +) %>% + cleanepi::add_to_dictionary( + option = "1", + value = "male", + grp = "sex", + order = NULL + ) + +new_dictionary +``` + +Puedes leer más detalles en la sección sobre "Sustitución de datos basada en el diccionario" del paquete +[Viñeta "Primeros pasos"](https://epiverse-trace.github.io/cleanepi/articles/cleanepi.html#dictionary-based-data-substituting). + +:::::::::::::::::::::::::: + +### Calcular el intervalo de tiempo entre diferentes eventos de fecha + +En el análisis de datos epidemiológicos, también es útil seguir y analizar acontecimientos dependientes del tiempo, como la progresión +de un brote de enfermedad (es decir, la diferencia de tiempo entre el día de hoy y el primer caso notificado) o la duración entre +la recogida de muestras y el análisis (es decir, la diferencia de tiempo entre hoy y la recolección de muestras). Lo más habitual +es calcular la edad de todos los sujetos a partir de su fecha de nacimiento (es decir, la diferencia de tiempo entre el día de hoy +y la fecha de nacimiento). + +En `{cleanepi}` se ofrece una cómoda función para calcular el tiempo transcurrido entre dos acontecimientos en +diferentes escalas temporales. Por ejemplo, el siguiente fragmento de código utiliza la función `cleanepi::timespan()` para calcular el +tiempo transcurrido desde la fecha de la muestra para el caso identificado +hasta la fecha en que se generó este documento (`r Sys.Date()`). + +```{r} +sim_ebola_data <- cleanepi::timespan( + sim_ebola_data, + target_column = "date_sample", + end_date = Sys.Date(), + span_unit = "years", + span_column_name = "years_since_collection", + span_remainder_unit = "months" +) + +sim_ebola_data %>% + dplyr::select(case_id, date_sample, years_since_collection, remainder_months) +``` + +Después de ejecutar la función `cleanepi::timespan()` dos nuevas columnas llamadas `years_since_collection` y +`remainder_months` se añaden a **sim\_ebola\_datos** que contiene el tiempo transcurrido calculado desde la fecha +de recolección de la muestra para cada caso, medido en años, y el tiempo restante medido en meses. + +::::::::::::::::::::::::::::::::::::::::::::::: desafío + +Los datos de edad son útiles en cualquier análisis posterior. Puedes categorizarlos para generar estimaciones estratificadas. + +Lee los `test_df.RDS` marco de datos dentro del `{cleanepi}` paquete: + +```{r} +dat <- readRDS( + file = system.file("extdata", "test_df.RDS", package = "cleanepi") +) %>% + dplyr::as_tibble() +``` + +Calcular la edad en años de los sujetos con fecha de nacimiento, y el tiempo restante en meses. Limpia y normaliza los elementos necesarios para conseguirlo. + +:::::::::::::::::::::::::::: pista + +Antes de calcular la edad, puede que necesites + +- normalizar los nombres de las columnas +- normalizar fechas columnas +- reemplazar las cadenas con datos faltantes por una entrada de datos faltantes válida + +:::::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solución + +En la solución añadimos `date_first_pcr_positive_test` dado que proporcionará la escala temporal para el análisis descriptivo y estadístico posterior del brote de la enfermedad. + +```{r} +dat_clean <- dat %>% + # estandarizar los nombres de columnas y las fechas + cleanepi::standardize_column_names() %>% + cleanepi::standardize_dates( + target_columns = c("date_of_birth", "date_first_pcr_positive_test") + ) %>% + # reemplazar desde cadenas de caracteres por entradas con valores faltantes que + # son válidas + cleanepi::replace_missing_values( + target_columns = "sex", + na_strings = "-99" + ) %>% + # calcular la edad en años y devolver el tiempo restante en meses + cleanepi::timespan( + target_column = "date_of_birth", + end_date = Sys.Date(), + span_unit = "years", + span_column_name = "age_in_years", + span_remainder_unit = "months" + ) +``` + +Ahora, ¿cómo categorizarías una variable numérica? + +:::::::::::::::::::::::::: + +:::::::::::::::::::::::::: solución + +La alternativa más sencilla es utilizar `Hmisc::cut2()`. También puedes utilizar `dplyr::case_when()` sin embargo, esto requiere más líneas de código y es más apropiado para categorizaciones personalizadas. Aquí ofrecemos una solución utilizando `base::cut()`: + +```{r} +dat_clean %>% + # seleccionar para ver cómodamente los resultados de los intervalos de tiempo + dplyr::select( + study_id, + sex, + date_first_pcr_positive_test, + date_of_birth, + age_in_years + ) %>% + # categorizar la variable numérica edad [añadir como pista de desafío]. + dplyr::mutate( + age_category = base::cut( + x = age_in_years, + breaks = c(0, 20, 35, 60, Inf), # reemplazar con el valor máximo si es conocido + include.lowest = TRUE, + right = FALSE + ) + ) +``` + +Puedes investigar los valores máximos de las variables utilizando `skimr::skim()` en lugar de `base::cut()`. También puedes utilizar +`Hmisc::cut2(x = age_in_years,cuts = c(20,35,60))` que calcula el valor máximo y no requiere más +argumentos. + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::::::::::::: + +## Varias operaciones a la vez + +Realizar las operaciones de limpieza de datos individualmente puede llevar mucho tiempo y ser propenso a errores. El sitio del paquete `{cleanepi}` +simplifica este proceso ofreciendo una cómoda función envolvente llamada `clean_data()` que te permite realizar +varias operaciones a la vez. + +La página `clean_data()` aplica una serie de operaciones predefinidas de limpieza de datos al conjunto de datos de entrada. Aquí tienes un +fragmento de código de ejemplo que ilustra cómo utilizar `clean_data()` en un conjunto de datos de Ébola simulado sin procesar: + +Además, puedes combinar varias tareas de limpieza de datos mediante el operador pipe "%>%", como se muestra en el código siguiente: + +```{r, warning=FALSE, message=FALSE} +# Realiza las operaciones de limpieza mediante el operador pipe (%>%) +cleaned_data <- raw_ebola_data %>% + cleanepi::standardize_column_names() %>% + cleanepi::remove_constants() %>% + cleanepi::remove_duplicates() %>% + cleanepi::replace_missing_values(na_strings = "") %>% + cleanepi::check_subject_ids( + target_columns = "case_id", + range = c(1, 15000) + ) %>% + cleanepi::standardize_dates( + target_columns = c("date_onset", "date_sample") + ) %>% + cleanepi::convert_to_numeric(target_columns = "age") %>% + cleanepi::check_date_sequence( + target_columns = c("date_onset", "date_sample") + ) %>% + cleanepi::clean_using_dictionary(dictionary = test_dict) %>% + cleanepi::timespan( + target_column = "date_sample", + end_date = Sys.Date(), + span_unit = "years", + span_column_name = "years_since_collection", + span_remainder_unit = "months" + ) +``` + +```{r, echo=FALSE, eval=TRUE} +cleaned_data %>% + write_csv(file = file.path("data", "cleaned_data.csv")) +``` + +## Informe de limpieza + +El paquete `{cleanepi}` genera un informe completo en el que se detallan las conclusiones y acciones de toda la limpieza de datos +realizadas durante el análisis. Este informe se presenta como una página web con varias secciones. Cada sección +corresponde a una operación específica de limpieza de datos, y al hacer clic en cada sección puedes acceder a los resultados de +esa operación concreta. Este enfoque interactivo permite a los usuarios revisar y analizar eficazmente los resultados de +pasos individuales de limpieza dentro del proceso más amplio de limpieza de datos. + +Puedes ver el informe utilizando la función `cleanepi::print_report(cleaned_data)`. + +

+ Informe de limpieza de datos +

+

Ejemplo de informe de limpieza de datos generado por `{cleanepi}`

+
+ + +::::::::::::::::::::::::::::::::::::: puntos clave + +- Utilizar `{cleanepi}` para limpiar y normalizar los datos de epidemias y brotes epidémicos +- Comprender cómo utilizar `{cleanepi}` para realizar tareas comunes de limpieza de datos y operaciones relacionadas con la epidemiología +- Ver el informe de limpieza de datos en un navegador, consultarlo y tomar decisiones. + +::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/es/describe-cases.Rmd b/locale/es/describe-cases.Rmd new file mode 100644 index 00000000..442f9180 --- /dev/null +++ b/locale/es/describe-cases.Rmd @@ -0,0 +1,372 @@ +--- +title: Agrega y visualiza +teaching: 20 +exercises: 10 +--- + +:::::::::::::::::::::::::::::::::::::: preguntas + +- ¿Cómo agregar datos de casos? +- ¿Cómo visualizar los datos agregados? +- ¿Cuál es la distribución de los casos en el tiempo, lugar, sexo, edad? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objetivos + +- Simular datos sintéticos de brotes +- Convertir los datos de la lista de líneas en incidencia +- Crear curvas epidémicas a partir de datos de incidencia + :::::::::::::::::::::::::::::::::::::::::::::::: + +## Introducción + +En una cadena analítica, el análisis exploratorio de datos (AED) es un paso importante antes de la modelización formal. El AED ayuda a +determinar las relaciones entre variables y resumir sus características principales, a menudo mediante la visualización de datos. + +Este episodio se centra en el EDA de datos de brotes epidémicos utilizando algunos paquetes esenciales de R. +Un aspecto clave del EDA en el análisis de epidemias es identificar la relación entre el tiempo y el resultado epidémico observado, como los casos confirmados, las hospitalizaciones, las muertes y las recuperaciones en diferentes lugares y factores demográficos, como el sexo, la edad, etc. + +Empecemos cargando el paquete `{incidence2}` para agregar los datos de la lista de líneas por grupos y visualizar las epicurvas. +Utilizaremos `{simulist}` para simular datos de brotes, y `{tracetheme}` para dar formato a las figuras complementarias. +Utilizaremos la tubería `%>%` para conectar algunas de sus funciones, incluidas otras de los paquetes `{dplyr}` y +`{ggplot2}` así que vamos a llamar también al paquete tidyverse: + +```{r, eval=TRUE, message=FALSE, warning=FALSE} +# Load packages +library(incidence2) # For aggregating and visualising +library(simulist) # For simulating linelist data +library(tracetheme) # For formatting figures +library(tidyverse) # For {dplyr} and {ggplot2} functions and the pipe %>% +``` + +::::::::::::::::::: lista de control + +### El doble punto + +El doble punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza `filter()` del `{dplyr}` paquete. +Esto nos ayuda a recordar las funciones del paquete y a evitar conflictos de espacio de nombres. + +::::::::::::::::::: + +## Datos sintéticos de brotes + +Para ilustrar el proceso de realizar el AED sobre los datos del brote, generaremos una lista de líneas +de un hipotético brote de enfermedad utilizando el método `{simulist}` paquete. `{simulist}` genera datos de simulación para el brote según una configuración dada. +Su configuración mínima puede generar una lista de líneas como se muestra en el siguiente fragmento de código + +```{r} +# Simulate linelist data for an outbreak with size between 1000 and 1500 +set.seed(1) # Set seed for reproducibility +sim_data <- simulist::sim_linelist(outbreak_size = c(1000, 1500)) %>% + dplyr::as_tibble() # for a simple data frame output + +# Display the simulated dataset +sim_data +``` + +Este conjunto de datos de la lista de líneas ofrece información a nivel individual sobre el brote. + +::::::::::::::::::: spoiler + +## Recursos adicionales sobre datos de brotes epidémicos + +Esta es la configuración por defecto de `{simulist}` si quieres saber más sobre sus funcionalidades +consulta la página [sitio web de documentación](https://epiverse-trace.github.io/simulist/). + +También puedes encontrar conjuntos de datos de emergencias reales del pasado en la web [`{outbreaks}` Paquete R](https://www.reconverse.org/outbreaks/). + +::::::::::::::::::: + +## Agregando + +El análisis descendente implica trabajar con datos agregados en lugar de con casos individuales. Para ello es necesario agrupar la lista de líneas + en forma de datos de incidencia. La dirección [incidencia2] (([https://www.reconverse.org/incidence2/articles/incidence2.html){.externo +](https://www.reconverse.org/incidence2/articles/incidence2.html\){.external) target="\_blank"}) +ofrece una función esencial, llamada `incidence2::incidence()` para agrupar datos de casos, normalmente centrados en acontecimientos fechados +y/u otros factores. El fragmento de código que aparece a continuación muestra la creación de una función `` de la clase +Ébola simulado `linelist` a partir de la fecha de inicio. + +```{r} +# Create an incidence object by aggregating case data based on the date of onset +dialy_incidence <- incidence2::incidence( + sim_data, + date_index = "date_onset", + interval = "day" # Aggregate by daily intervals +) + +# View the incidence data +dialy_incidence +``` + +Además, con la `{incidence2}` paquete, puedes especificar el intervalo deseado y clasificar los casos por uno o +más factores. A continuación se muestra un fragmento de código que muestra casos semanales agrupados por fecha de inicio y sexo. + +```{r} +# Group incidence data by week, accounting for sex and case type +weekly_incidence <- incidence2::incidence( + sim_data, + date_index = "date_onset", + interval = "week", # Aggregate by weekly intervals + groups = c("sex", "case_type") # Group by sex and case type +) + +# View the incidence data +weekly_incidence +``` + +::::::::::::::::::::::::::::::::::::: llamada + +## Fechas Finalización + +Cuando los casos se agrupan por diferentes factores, es posible que estos grupos tengan diferentes intervalos de fechas en el +resultante. `incidence2` resultante. La dirección `incidence2` proporciona una función llamada `complete_dates()` para garantizar que un +objeto incidencia tiene el mismo rango de fechas para cada grupo. Por defecto, los recuentos que falten se rellenarán con 0. + +Esta funcionalidad también está disponible como argumento dentro de `incidence2::incidence()` añadir `complete_dates = TRUE`. + +```{r} +# Create an incidence object grouped by sex, aggregating daily +dialy_incidence_2 <- incidence2::incidence( + sim_data, + date_index = "date_onset", + groups = "sex", + interval = "day", # Aggregate by daily intervals + complete_dates = TRUE # Complete missing dates in the incidence object +) +``` + +```{r, echo=FALSE, eval=FALSE} +dialy_incidence_2_complete <- incidence2::complete_dates( + x = dialy_incidence_2, + expand = TRUE, # Expand to fill in missing dates + fill = 0L, # Fill missing values with 0 + by = 1L, # Fill by daily intervals + allow_POSIXct = FALSE # Ensure that dates are not in POSIXct format +) +``` + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: desafío + +## Reto 1: ¿Puedes hacerlo? + +- **Tarea**: Agregado `sim_data` lista de líneas basada en la fecha de admisión y el resultado del caso en **quincenalmente** + y guarda los resultados en un objeto llamado `biweekly_incidence`. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Visualización + +En `incidence2` puede visualizarse mediante la función `plot()` del paquete base de R. +El gráfico resultante se denomina curva epidémica, o epi-curva para abreviar. El código siguiente +generan curvas epidémicas para la función `dialy_incidence` y `weekly_incidence` mencionados anteriormente. + +```{r} +# Plot daily incidence data +base::plot(dialy_incidence) + + ggplot2::labs( + x = "Time (in days)", # x-axis label + y = "Dialy cases" # y-axis label + ) + + tracetheme::theme_trace() # Apply the custom trace theme +``` + +```{r} +# Plot weekly incidence data +base::plot(weekly_incidence) + + ggplot2::labs( + x = "Time (in weeks)", # x-axis label + y = "weekly cases" # y-axis label + ) + + tracetheme::theme_trace() # Apply the custom trace theme +``` + +:::::::::::::::::::::::: llamada + +#### estética fácil + +Te invitamos a hojear el `{incidence2}` paquete ["Viñeta "Empezar](https://www.reconverse.org/incidence2/articles/incidence2.html). Descubre cómo puedes utilizar argumentos dentro de `plot()` ¡para dotar de estética a tus objetos de la clase Incidencia2! + +```{r} +base::plot(weekly_incidence, fill = "sex") +``` + +Algunos de ellos son `show_cases = TRUE`, `angle = 45` y `n_breaks = 5`. ¡Pruébalos! + +:::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: desafío + +## Reto 2: ¿Puedes hacerlo? + +- **Tarea**: Visualizar `biweekly_incidence` objeto. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Curva de casos acumulados + +El número acumulado de casos puede calcularse mediante la función `cumulate()` a partir de una `incidence2` y visualizarlo, como en el ejemplo siguiente. + +```{r} +# Calculate cumulative incidence +cum_df <- incidence2::cumulate(dialy_incidence) + +# Plot cumulative incidence data using ggplot2 +base::plot(cum_df) + + ggplot2::labs( + x = "Time (in days)", # x-axis label + y = "weekly cases" # y-axis label + ) + + tracetheme::theme_trace() # Apply the custom trace theme +``` + +Ten en cuenta que esta función conserva la agrupación, es decir, si el `incidence2` contiene grupos, acumulará los casos en consecuencia. + +::::::::::::::::::::::::::::::::::::: desafío + +## Reto 3: ¿Puedes hacerlo? + +- **Tarea**: Visulaizar los casos acumulativos de `biweekly_incidence` objeto. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Estimación del pico + +Se puede estimar el pico --el momento con el mayor número de casos registrados-- utilizando la función `estimate_peak()` de la función {incidence2} paquete. +Esta función emplea un método de bootstrapping para determinar la hora punta. + +```{r} +# Estimate the peak of the daily incidence data +peak <- incidence2::estimate_peak( + dialy_incidence, + n = 100, # Number of simulations for the peak estimation + alpha = 0.05, # Significance level for the confidence interval + first_only = TRUE, # Return only the first peak found + progress = FALSE # Disable progress messages +) + +# Display the estimated peak +print(peak) +``` + +Este ejemplo muestra cómo estimar la hora punta utilizando la función `estimate_peak()` en $95%$ +intervalo de confianza y utilizando 100 muestras bootstrap. + +::::::::::::::::::::::::::::::::::::: desafío + +## Reto 4: ¿Puedes hacerlo? + +- **Tarea** Estimar la hora punta de `biweekly_incidence` objeto. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +## Visualización con ggplot2 + +`{incidence2}` produce gráficos básicos para epicurvas, pero se requiere un trabajo adicional para crear gráficos bien anotados. Sin embargo, utilizando la función `{ggplot2}` puedes generar epicurvas más sofisticadas y mejor anotadas. +`{ggplot2}` es un paquete completo con muchas funcionalidades. Sin embargo, nos centraremos en tres elementos clave para producir epicurvas: los gráficos de histograma, la escala de los ejes de fechas y sus etiquetas, y la anotación general del tema del gráfico. +El ejemplo siguiente muestra cómo configurar estos tres elementos para un simple `{incidence2}` objeto. + +```{r} +# Define date breaks for the x-axis +breaks <- seq.Date( + from = min(as.Date(dialy_incidence$date_index, na.rm = TRUE)), + to = max(as.Date(dialy_incidence$date_index, na.rm = TRUE)), + by = 20 # every 20 days +) + +# Create the plot +ggplot2::ggplot(data = dialy_incidence) + + geom_histogram( + mapping = aes( + x = as.Date(date_index), + y = count + ), + stat = "identity", + color = "blue", # bar border color + fill = "lightblue", # bar fill color + width = 1 # bar width + ) + + theme_minimal() + # apply a minimal theme for clean visuals + theme( + plot.title = element_text(face = "bold", + hjust = 0.5), # center and bold title + plot.subtitle = element_text(hjust = 0.5), # center subtitle + plot.caption = element_text(face = "italic", + hjust = 0), # italicized caption + axis.title = element_text(face = "bold"), # bold axis titles + axis.text.x = element_text(angle = 45, vjust = 0.5) # rotated x-axis text + ) + + labs( + x = "Date", # x-axis label + y = "Number of cases", # y-axis label + title = "Daily Outbreak Cases", # plot title + subtitle = "Epidemiological Data for the Outbreak", # plot subtitle + caption = "Data Source: Simulated Data" # plot caption + ) + + scale_x_date( + breaks = breaks, # set custom breaks on the x-axis + labels = scales::label_date_short() # shortened date labels + ) +``` + +Utiliza la función `group` en la función de mapeo para visualizar una epicurva con diferentes grupos. Si hay más de un factor de agrupación, utiliza la opción `facet_wrap()` como se muestra en el ejemplo siguiente: + +```{r} +# Plot daily incidence by sex with facets +ggplot2::ggplot(data = dialy_incidence_2) + + geom_histogram( + mapping = aes( + x = as.Date(date_index), + y = count, + group = sex, + fill = sex + ), + stat = "identity" + ) + + theme_minimal() + # apply minimal theme + theme( + plot.title = element_text(face = "bold", + hjust = 0.5), # bold and center the title + plot.subtitle = element_text(hjust = 0.5), # center the subtitle + plot.caption = element_text(face = "italic", hjust = 0), # italic caption + axis.title = element_text(face = "bold"), # bold axis labels + axis.text.x = element_text(angle = 45, + vjust = 0.5) # rotate x-axis text for readability + ) + + labs( + x = "Date", # x-axis label + y = "Number of cases", # y-axis label + title = "Daily Outbreak Cases by Sex", # plot title + subtitle = "Incidence of Cases Grouped by Sex", # plot subtitle + caption = "Data Source: Simulated Data" # caption for additional context + ) + + facet_wrap(~sex) + # create separate panels by sex + scale_x_date( + breaks = breaks, # set custom date breaks + labels = scales::label_date_short() # short date format for x-axis labels + ) + + scale_fill_manual(values = c("lightblue", + "lightpink")) # custom fill colors for sex +``` + +::::::::::::::::::::::::::::::::::::: desafío + +## Desafío 5: ¿Puedes hacerlo? + +- **Tarea**: Elabora una figura anotada para incidencia\_semanal utilizando `{ggplot2}` paquete. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: puntos clave + +- Utiliza `{simulist}` para generar datos sintéticos de brotes +- Utiliza `{incidence2}` para agregar datos de casos en función de una fecha y producir curvas epidémicas. +- Utiliza `{ggplot2}` para producir epicurvas mejor anotadas. + +:::::::::::::::::::::::::::::::::::::::::::::::: + + diff --git a/locale/es/validate.Rmd b/locale/es/validate.Rmd new file mode 100644 index 00000000..b20fc7ba --- /dev/null +++ b/locale/es/validate.Rmd @@ -0,0 +1,392 @@ +--- +title: Validar los datos del caso +teaching: 10 +exercises: 2 +--- + +:::::::::::::::::::::::::::::::::::::: preguntas + +- ¿Cómo convertir un conjunto de datos en bruto en un `linelist` objeto? + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: objetivos + +- Demostrar cómo encubrir datos de casos para `linelist` datos +- Demostrar cómo validar los datos + +:::::::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::: prerrequisito + +Este episodio requiere que + +- Descargar el [datos\_limpiados.csv](https://epiverse-trace.github.io/tutorials-early/data/cleaned_data.csv) +- Guárdalo en la carpeta `data/` carpeta. + +::::::::::::::::::::: + +## Introducción + +En el análisis de brotes, una vez que has completado los pasos iniciales de lectura y limpieza de los datos del caso, +es esencial establecer una capa de cimentación adicional para garantizar la integridad y fiabilidad de los posteriores +análisis posteriores. En concreto, esto implica verificar la presencia y el tipo de datos correcto de determinadas columnas dentro de +tu conjunto de datos, un proceso comúnmente denominado "etiquetado". Además, es crucial aplicar medidas para +validar que estas columnas etiquetadas no se eliminen inadvertidamente durante los pasos posteriores del procesamiento de datos. + +Este episodio se centra en el etiquetado y la validación de los datos de los brotes utilizando la función [lista de líneas](https://epiverse-trace.github.io/linelist/) +paquete. Empecemos cargando el paquete `{rio}` para leer datos y el paquete `{linelist}` +para crear una lista de líneas. Utilizaremos la tubería `%>%` para conectar algunas de sus funciones, incluidas otras de +el paquete `{dplyr}` así que vamos a llamar también al paquete tidyverse: + +```{r, eval=TRUE, message=FALSE, warning=FALSE} +# Load packages +library(tidyverse) # for {dplyr} functions and the pipe %>% +library(rio) # for importing data +library(here) # for easy file referencing +library(linelist) # for taggin and validating +``` + +::::::::::::::::::: lista de comprobación + +### El doble punto + +El doble punto `::` en R te permite llamar a una función específica de un paquete sin cargar todo el paquete en la función +en el entorno actual. + +Por ejemplo `dplyr::filter(data, condition)` utiliza `filter()` del `{dplyr}` paquete. + +Esto nos ayuda a recordar las funciones del paquete y a evitar conflictos de espacio de nombres. + +::::::::::::::::::: + +Importa el conjunto de datos siguiendo las directrices indicadas en el [Leer datos de casos](../episodes/read-cases.Rmd) episodio. +Se trata de cargar el conjunto de datos en el entorno de trabajo y ver su estructura y contenido. + +```{r, eval=FALSE} +# Read data +# e.g.: if path to file is data/simulated_ebola_2.csv then: +cleaned_data <- rio::import( + here::here("data", "cleaned_data.csv") +) %>% + dplyr::as_tibble() # for a simple data frame output +``` + +```{r, echo=FALSE} +# Import cleaned data without printing code +cleaned_data <- rio::import( + file.path("data", "cleaned_data.csv") +) %>% + dplyr::as_tibble() # Convert to tibble for better data display + +# Display the first five rows of the dataset +cleaned_data +``` + +:::::::::::::::::::::::: discusión + + + +### Un cambio inesperado + +Te encuentras en una situación de respuesta de emergencia. Necesitas generar informes de situación diarios. Has automatizado tu análisis para leer los datos directamente del servidor online :grin:. Sin embargo, las personas encargadas de la recogida/administración de datos necesitaban **eliminar/renombrar/reformatear** ¡una variable que te resultó útil :disappointed:! + +¿Cómo puedes detectar si la entrada de datos es **sigue siendo válida** para replicar el código de análisis que escribiste el día anterior? + +:::::::::::::::::::::::: + +:::::::::::::::::::::::: instructor + +Si los alumnos no tienen una experiencia que compartir, nosotros, como instructores, podemos compartir una. + +Un escenario como éste suele darse cuando la institución que realiza el análisis no es la misma que la que recopila los datos. Esta última puede tomar decisiones sobre la estructura de los datos que pueden afectar a los procesos posteriores, repercutiendo en el tiempo o en la precisión de los resultados del análisis. + +:::::::::::::::::::::::: + +## Crear una lista de líneas y etiquetar elementos + +A continuación, convertimos los datos de casos depurados en una `linelist` objeto utilizando `{linelist}` ver el paquete +siguiente fragmento de código. + +```{r} +# Create a linelist object from cleaned data +linelist_data <- linelist::make_linelist( + x = cleaned_data, # Input data + id = "case_id", # Column for unique case identifiers + date_onset = "date_onset", # Column for date of symptom onset + gender = "gender" # Column for gender +) + +# Display the resulting linelist object +linelist_data +``` + +La dirección `{linelist}` proporciona etiquetas para variables epidemiológicas comunes +y un conjunto de tipos de datos apropiados para cada una. Puedes ver la lista de etiquetas disponibles por el nombre de la variable +y los tipos de datos aceptables para cada una utilizando `linelist::tags_types()`. + +::::::::::::::::::::::::::::::::::::: desafío + +Vamos a **etiqueta** más variables. En los nuevos conjuntos de datos, será frecuente que los nombres de las variables sean distintos de los nombres de las etiquetas disponibles. Sin embargo, podemos asociarlos basándonos en cómo se definieron las variables para la recogida de datos. + +Ahora: + +- **Explora** los nombres de etiquetas disponibles en {linelist}. +- **Encuentra** qué otras variables del conjunto de datos depurado pueden asociarse a cualquiera de estas etiquetas disponibles. +- **Etiqueta** esas variables como arriba utilizando `linelist::make_linelist()`. + +:::::::::::::::::::: pista + +Puedes acceder a la lista de nombres de etiquetas disponibles en {linelist} utilizando: + +```{r, eval=FALSE} +# Get a list of available tags by name and data types +linelist::tags_types() + +# Get a list of names only +linelist::tags_names() +``` + +::::::::::::::::::::::: + +::::::::::::::::: solución + +```{r, eval=FALSE} +linelist::make_linelist( + x = cleaned_data, + id = "case_id", + date_onset = "date_onset", + gender = "gender", + age = "age", # same name in default list and dataset + date_reporting = "date_sample" # different names but related +) +``` + +¿Cómo se ven estas etiquetas adicionales en la salida? + +:::::::::::::::::::::::::: +:::::::::::::::::::::::::::::::::::::::::::::: + +## Validación + +Para garantizar que todas las variables etiquetadas están normalizadas y tienen los datos correctos +correctos, utiliza la función `linelist::validate_linelist()` como +que se muestra en el ejemplo siguiente: + +```r +linelist::validate_linelist(linelist_data) +``` + + + + + + + +::::::::::::::::::::::::: desafío + +Vamos a **validar** variables etiquetadas. Simulemos que en un brote en curso; al día siguiente, tus datos tienen un nuevo conjunto de entradas (es decir, filas u observaciones) pero una variable cambia de tipo de datos. + +Por ejemplo, hagamos que la variable `age` cambie de tipo de un doble (``) a variable carácter (``). + +Para simularlo: + +- **Cambia** el tipo de datos de la variable, +- **Etiqueta** la variable en una lista de líneas, y luego +- **Valida** lo. + +Describe cómo `linelist::validate_linelist()` reacciona cuando los datos de entrada tienen un tipo de dato variable diferente. + +:::::::::::::::::::::::::: sugerencia + +Podemos utilizar `dplyr::mutate()` para cambiar el tipo de variable antes de etiquetarla para su validación. Por ejemplo: + +```{r, eval=FALSE} +cleaned_data %>% + # simulate a change of data type in one variable + dplyr::mutate(age = as.character(age)) %>% + # tag one variable + linelist::... %>% + # validate the linelist + linelist::... +``` + +:::::::::::::::::::::::::: + +:::::::::::::::::::::::::: sugerencia + +> Por favor, ejecuta el código línea por línea, centrándote sólo en las partes que están antes de la tubería (`%>%`). Después de cada paso, observa la salida antes de pasar a la línea siguiente. + +Si la `age` cambia de doble (``) a carácter (``) obtenemos lo siguiente: + +```{r} +cleaned_data %>% + # simulate a change of data type in one variable + dplyr::mutate(age = as.character(age)) %>% + # tag one variable + linelist::make_linelist( + age = "age" + ) %>% + # validate the linelist + linelist::validate_linelist() +``` + +¿Por qué recibimos una `Error` mensaje? + + + +Explora otras situaciones para comprender este comportamiento. Probemos estos cambios adicionales en las variables: + +- `date_onset` cambios de a `` variable a carácter (``), +- `gender` cambia de un carácter (``) a una variable entera (``). + +A continuación, etiquétalos en una lista de líneas para su validación. ¿El `Error` mensaje nos propone la solución? + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::: solución + +```{r, eval=FALSE} +# Change 2 +# Run this code line by line to identify changes +cleaned_data %>% + # simulate a change of data type + dplyr::mutate(date_onset = as.character(date_onset)) %>% + # tag + linelist::make_linelist( + date_onset = "date_onset" + ) %>% + # validate + linelist::validate_linelist() +``` + +```{r, eval=FALSE} +# Change 3 +# Run this code line by line to identify changes +cleaned_data %>% + # simulate a change of data type + dplyr::mutate(gender = as.factor(gender)) %>% + dplyr::mutate(gender = as.integer(gender)) %>% + # tag + linelist::make_linelist( + gender = "gender" + ) %>% + # validate + linelist::validate_linelist() +``` + +Obtenemos `Error` debido a la falta de correspondencia entre el tipo de etiqueta predefinido (de `linelist::tags_types()`) y la clase de variable etiquetada en la lista de líneas. + +En `Error` mensaje nos informa de que para **validar** nuestra lista de líneas, debemos arreglar el tipo de variable de entrada para que se ajuste al tipo de etiqueta esperado. En un script de análisis de datos, podemos hacerlo añadiendo un paso de limpieza a la cadena. + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: + +::::::::::::::::::::::::: desafío + +¿Qué paso a lo largo del `{linelist}` flujo de trabajo de etiquetado y validación respondería a la ausencia de una variable? + +:::::::::::::::::::::::::: solución + +Sobre la pérdida de variables, puedes simular este escenario: + +```{r} +cleaned_data %>% + # simulate a change of data type in one variable + select(-age) %>% + # tag one variable + linelist::make_linelist( + age = "age" + ) +``` + +:::::::::::::::::::::::::: + +::::::::::::::::::::::::: + +## Protección + +La salvaguarda está implícita en los objetos de la lista de líneas. Si intentas soltar alguno de los objetos etiquetados +recibirás un mensaje de error o advertencia, como se muestra en el ejemplo siguiente. + +```{r, warning=TRUE} +new_df <- linelist_data %>% + dplyr::select(case_id, gender) +``` + +Este `Warning` mensaje anterior es la opción de salida por defecto cuando perdemos etiquetas en un `linelist` objeto. Sin embargo, se puede cambiar por un `Error` mensaje utilizando `linelist::lost_tags_action()`. + +::::::::::::::::::::::::::::::::::::: desafío + +Probemos las implicaciones de cambiar el **salvaguarda** de una configuración `Warning` a una `Error` mensaje. + +- Primero, ejecuta este código para contar la frecuencia por categoría dentro de una variable categórica: + +```{r, eval=FALSE} +linelist_data %>% + dplyr::select(case_id, gender) %>% + dplyr::count(gender) +``` + +- Establecer el comportamiento de las etiquetas perdidas en una `linelist` a "error" como sigue: + +```{r, eval=FALSE} +# set behavior to "error" +linelist::lost_tags_action(action = "error") +``` + +- Ahora, vuelve a ejecutar el segmento de código anterior con `dplyr::count()`. + +Identificar: + +- ¿Cuál es la diferencia de rendimiento entre un `Warning` y un `Error`? +- ¿Cuáles podrían ser las implicaciones de este cambio para tu proceso diario de análisis de datos durante la respuesta a un brote? + +:::::::::::::::::::::::: solución + +Decidir entre `Warning` o `Error` dependerá del nivel de atención o flexibilidad que necesites al perder etiquetas. Uno te alertará de un cambio pero seguirá ejecutando el código aguas abajo. El otro detendrá tu canal de análisis y el resto no se ejecutará. + +Un script de lectura, limpieza y validación de datos puede requerir un pipeline más estable o fijo. Un análisis exploratorio de datos puede requerir un enfoque más flexible. Estos dos procesos pueden aislarse en scripts o repositorios diferentes para ajustar la salvaguarda según tus necesidades. + +Antes de continuar, restablece la configuración a la opción por defecto de `Warning`: + +```{r} +# set behavior to the default option: "warning" +linelist::lost_tags_action() +``` + +:::::::::::::::::::::::: + +:::::::::::::::::::::::::::::::::::::::::::::::: + +A `linelist` objeto se parece a un marco de datos, pero ofrece características más ricas +y funcionalidades más ricas. Los paquetes que tienen en cuenta las listas de líneas pueden aprovechar estas +características. Por ejemplo, puedes extraer un marco de datos de sólo las columnas etiquetadas +utilizando la función `linelist::tags_df()` como se muestra a continuación: + +```{r, warning=FALSE} +linelist::tags_df(linelist_data) +``` + +Esto permite, la extracción del uso de columnas sólo etiquetadas en análisis posteriores, ¡lo que será útil para el próximo episodio! + +:::::::::::::::::::::::::::::::::::: lista de comprobación + +### ¿Cuándo debo utilizar `{linelist}`? + +El análisis de datos durante la respuesta a un brote o la vigilancia de recogida masiva exige un conjunto diferente de "salvaguardias de datos" si se compara con las situaciones habituales de investigación. Por ejemplo, tus datos cambiarán o se actualizarán con el tiempo (por ejemplo, nuevas entradas, nuevas variables, variables renombradas). + +`{linelist}` es más apropiado para este tipo de análisis continuo o duradero. +Consulta la sección de viñetas "Para empezar" sobre +[Cuándo debes plantearte utilizar {linelist}?](https://epiverse-trace.github.io/linelist/articles/linelist.html#should-i-use-linelist) para obtener más información. + +::::::::::::::::::::::::::::::::::::::::::: + +::::::::::::::::::::::::::::::::::::: puntos clave + +- Utiliza `{linelist}` para etiquetar, validar y preparar los datos de los casos para su posterior análisis. + +:::::::::::::::::::::::::::::::::::::::::::::::: + +