10  Manipulación de Datos con Herramientas Base de R

La manipulación de datos con herramientas base de R constituye una etapa esencial en el flujo de trabajo estadístico clásico. Antes de aplicar técnicas como el análisis de varianza, la regresión lineal o la comparación de medias, es necesario preparar los datos para asegurar su integridad y adecuación al análisis. Las funciones básicas de R permiten seleccionar, filtrar, transformar, agrupar y limpiar datos de manera eficiente, facilitando la obtención de resultados estadísticos válidos y reproducibles (R Core Team, 2023).

10.1 Datos de ejemplo

Para ilustrar las técnicas de manipulación, se emplea un conjunto de datos simulado que representa un experimento agrícola. Este conjunto contiene variables numéricas y categóricas, así como algunos valores faltantes, lo que permite demostrar operaciones comunes en la estadística clásica. El uso de datos simulados garantiza la reproducibilidad de los ejemplos y facilita la comprensión de los procedimientos (Wickham & Grolemund, 2017).

El objetivo de este ejemplo es mostrar cómo crear y explorar un conjunto de datos en R, identificando la estructura de las variables y la presencia de valores faltantes, aspectos fundamentales en la preparación de datos para el análisis estadístico.

Creación del conjunto de datos simulado

# Establecer una semilla para que el usuario pueda replicar el ejemplo
set.seed(123) # Garantiza reproducibilidad

# Simular los resultados de un experimento
# con el diseño bloques completos al azar
datos_cultivo <- data.frame(
  parcela = 1:20,
  tratamiento = rep(c("Control", 
                      "Fertilizante A", 
                      "Fertilizante B", 
                      "Fertilizante C"), each = 5),
  bloque = rep(1:5, times = 4),
  altura_cm = round(rnorm(20, mean = 65, sd = 10), 1),
  peso_gr = round(rnorm(20, mean = 120, sd = 25), 1),
  daño_plaga = sample(c("Alto", "Medio", "Bajo"), 20, replace = TRUE),
  fecha_siembra = as.Date("2024-01-01") + sample(1:10, 20, replace = TRUE)
)

En este bloque de código se crea un data frame denominado datos_cultivo que simula los resultados de un experimento agrícola bajo un diseño de bloques completos al azar. Las variables incluyen identificadores de parcela, tipo de tratamiento aplicado, bloque experimental, altura y peso de las plantas, nivel de daño por plaga y fecha de siembra. La función set.seed(123) asegura que los resultados sean reproducibles, permitiendo que cualquier usuario obtenga el mismo conjunto de datos al ejecutar el código.

Simulación de valores faltantes

# Simular la presencia de datos faltantes en los resultados del experimento
datos_cultivo$altura_cm[c(3, 15)] <- NA
datos_cultivo$peso_gr[c(7, 18)] <- NA

Se introducen valores faltantes (NA) en las variables altura_cm y peso_gr para reflejar situaciones reales en las que los datos pueden estar incompletos. Este paso es fundamental para demostrar técnicas de manejo de datos faltantes en secciones posteriores.

Visualización preliminar de los datos

# Visualizar las primeras filas del data frame con los datos simulados
head(datos_cultivo)
  parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
1       1        Control      1      59.4    93.3      Medio    2024-01-10
2       2        Control      2      62.7   114.6      Medio    2024-01-08
3       3        Control      3        NA    94.3       Bajo    2024-01-04
4       4        Control      4      65.7   101.8      Medio    2024-01-09
5       5        Control      5      66.3   104.4      Medio    2024-01-10
6       6 Fertilizante A      1      82.2    77.8       Bajo    2024-01-04

La función head() permite observar las primeras seis filas del data frame, facilitando la verificación de la correcta creación de las variables y la identificación de valores faltantes.

Es importante revisar la estructura y el contenido de los datos antes de proceder con cualquier análisis, ya que la presencia de valores faltantes o inconsistencias puede afectar la validez de los resultados estadísticos. Para ello también se puede usar la función view (), que nos permite visualizar un objeto en su totalidad en formato tabular (R Core Team, 2023).

10.2 Selección y filtrado de datos en data frames

La selección y el filtrado de datos constituyen operaciones fundamentales en la manipulación de data frames en R, ya que permiten enfocar el análisis en subconjuntos de información relevantes para los objetivos estadísticos planteados. Estas tareas se realizan mediante la indexación y el uso de condiciones lógicas, lo que facilita la extracción precisa de variables y observaciones de interés (Wickham & Grolemund, 2017; R Core Team, 2023).

10.2.1 Selección de columnas

En R, la selección de columnas dentro de un data frame se efectúa utilizando la notación de corchetes [, ], donde el primer argumento corresponde a las filas y el segundo a las columnas. Por ejemplo, para extraer únicamente las variables de altura y peso del conjunto de datos simulado, se emplea el siguiente código:

# Seleccionar solo las columnas de altura y peso del data frame
datos_mediciones <- datos_cultivo[, c("altura_cm", "peso_gr")]

# Visualizar las primeras filas para verificar la selección
head(datos_mediciones)
  altura_cm peso_gr
1      59.4    93.3
2      62.7   114.6
3        NA    94.3
4      65.7   101.8
5      66.3   104.4
6      82.2    77.8

En este caso, se especifican los nombres de las columnas deseadas dentro de un vector, lo que permite obtener un nuevo data frame que contiene exclusivamente las mediciones de altura y peso. Esta práctica es recomendable, ya que el uso de nombres de columnas, en lugar de posiciones numéricas, previene errores en caso de que la estructura del data frame cambie posteriormente.

La exclusión de columnas también puede realizarse de manera eficiente. Por ejemplo, si se requiere eliminar la variable de fecha de siembra, se puede utilizar la función names() junto con el operador %in% para identificar y excluir la columna correspondiente:

# Excluir la columna fecha_siembra del data frame
datos_sin_fecha <- datos_cultivo[, !names(datos_cultivo)
                                 %in% "fecha_siembra"]

# Verificar que la columna fecha_siembra ha sido eliminada
head(datos_sin_fecha)
  parcela    tratamiento bloque altura_cm peso_gr daño_plaga
1       1        Control      1      59.4    93.3      Medio
2       2        Control      2      62.7   114.6      Medio
3       3        Control      3        NA    94.3       Bajo
4       4        Control      4      65.7   101.8      Medio
5       5        Control      5      66.3   104.4      Medio
6       6 Fertilizante A      1      82.2    77.8       Bajo

Este procedimiento genera un nuevo data frame en el que la columna “fecha_siembra” ha sido removida, manteniendo el resto de las variables intactas. La visualización de las primeras filas permite comprobar que la exclusión se ha realizado correctamente.

Asimismo, la selección de columnas puede basarse en la posición que ocupan dentro del data frame:

# Seleccionar las tres primeras columnas usando índices numéricos
primeras_tres_columnas <- datos_cultivo[, 1:3]

# Mostrar el resultado para verificar la selección
head(primeras_tres_columnas)
  parcela    tratamiento bloque
1       1        Control      1
2       2        Control      2
3       3        Control      3
4       4        Control      4
5       5        Control      5
6       6 Fertilizante A      1

Este método resulta útil en situaciones donde se conoce la estructura del data frame y se requiere trabajar con un subconjunto de variables contiguas. Sin embargo, es importante considerar que la selección por posición puede ser menos robusta ante modificaciones en el orden de las columnas, por lo que se recomienda preferir la selección por nombre cuando sea posible.

10.2.2 Filtrado de filas por condiciones lógicas

El filtrado de filas en un data frame se realiza especificando una condición lógica en el argumento correspondiente a las filas dentro de la notación de corchetes. Por ejemplo, para seleccionar únicamente las observaciones que corresponden al tratamiento “Control”, se utiliza la siguiente instrucción:

# Filtrar las filas donde el tratamiento es "Control"
datos_control <- datos_cultivo[datos_cultivo$tratamiento == "Control", ]

# Verificar el filtrado mostrando las primeras filas
head(datos_control)
  parcela tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
1       1     Control      1      59.4    93.3      Medio    2024-01-10
2       2     Control      2      62.7   114.6      Medio    2024-01-08
3       3     Control      3        NA    94.3       Bajo    2024-01-04
4       4     Control      4      65.7   101.8      Medio    2024-01-09
5       5     Control      5      66.3   104.4      Medio    2024-01-10

En este caso, la condición datos_cultivo$tratamiento == "Control" evalúa cada fila del data frame y selecciona aquellas en las que la variable “tratamiento” coincide con el valor especificado. El resultado es un nuevo data frame que contiene únicamente las observaciones del grupo de control, lo que facilita la comparación o el análisis específico de este subconjunto.

El filtrado puede combinar múltiples condiciones lógicas para refinar aún más la selección de datos. Por ejemplo, si se desea obtener las observaciones en las que la altura es mayor a 65 centímetros y el tratamiento es distinto de “Control”, se puede emplear el siguiente código:

# Filtrar filas que cumplen dos condiciones simultáneamente
datos_altos <- datos_cultivo[datos_cultivo$altura_cm > 65 &
                             datos_cultivo$tratamiento != "Control", ]

# Verificar el resultado del filtrado
head(datos_altos)
   parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
6        6 Fertilizante A      1      82.2    77.8       Bajo    2024-01-04
7        7 Fertilizante A      2      69.6      NA       Bajo    2024-01-08
11      11 Fertilizante B      1      77.2   130.7       Alto    2024-01-11
12      12 Fertilizante B      2      68.6   112.6      Medio    2024-01-06
13      13 Fertilizante B      3      69.0   142.4       Alto    2024-01-06
14      14 Fertilizante B      4      66.1   142.0       Alto    2024-01-09

Aquí, la condición compuesta utiliza el operador lógico & para exigir que ambas condiciones se cumplan simultáneamente. De este modo, se obtiene un subconjunto de datos que cumple criterios específicos de interés para el análisis.

Para mejorar la legibilidad y evitar la repetición del nombre del data frame en cada condición, R ofrece la función subset(), que permite expresar las condiciones de filtrado de manera más clara. Por ejemplo, para seleccionar las observaciones correspondientes al tratamiento “Fertilizante A” y a los bloques 2, 3 o 4, se puede utilizar la siguiente instrucción:

# Usar subset() para filtrar datos de manera más legible
datos_fertilizante_A <- subset(datos_cultivo, 
                              tratamiento == "Fertilizante A" &
                              bloque %in% c(2,3,4))

# Mostrar el resultado del filtrado
head(datos_fertilizante_A)
  parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
7       7 Fertilizante A      2      69.6      NA       Bajo    2024-01-08
8       8 Fertilizante A      3      52.3   123.8       Alto    2024-01-04
9       9 Fertilizante A      4      58.1    91.5      Medio    2024-01-08

La función subset() interpreta las condiciones dentro del contexto del data frame especificado, lo que simplifica la sintaxis y reduce la posibilidad de errores. Esta función resulta especialmente útil cuando se trabaja con condiciones complejas o con múltiples variables.

La correcta aplicación de estas técnicas de selección y filtrado permite preparar conjuntos de datos ajustados a los requerimientos de los análisis estadísticos, optimizando la eficiencia y la claridad en la manipulación de la información (R Core Team, 2023; Wickham & Grolemund, 2017).

10.3 Modificación de variables

La modificación de variables constituye una etapa crucial en la preparación de datos para análisis estadísticos, ya que permite adaptar la información a los requerimientos específicos de diferentes métodos analíticos. Esta transformación de datos puede incluir la creación de nuevas variables derivadas, la recodificación de variables categóricas y la aplicación de transformaciones matemáticas para cumplir con los supuestos de las técnicas estadísticas (Wickham & Grolemund, 2017; R Core Team, 2023).

10.3.1 Creación de nuevas columnas

En R, la creación de nuevas variables se realiza mediante operaciones aritméticas o lógicas sobre las columnas existentes del data frame. Estas transformaciones permiten generar índices, categorizar datos continuos o aplicar transformaciones matemáticas para mejorar la normalidad de las distribuciones:

# Crear un índice que relaciona altura y peso
# La división genera una nueva variable que es el indice de crecimiento
datos_cultivo$indice_crecimiento <- 
  datos_cultivo$altura_cm/datos_cultivo$peso_gr

# Categorizar el peso en dos niveles usando una condición lógica
# ifelse() evalúa cada valor y asigna una categoría según la condición
datos_cultivo$categoria_peso <- ifelse(datos_cultivo$peso_gr > 120, 
                                      "Alto", "Bajo")

# Aplicar transformación logarítmica para normalizar la distribución
# log() es útil para variables con asimetría positiva
datos_cultivo$log_peso <- log(datos_cultivo$peso_gr)

# Verificar las nuevas variables creadas
head(datos_cultivo)
  parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
1       1        Control      1      59.4    93.3      Medio    2024-01-10
2       2        Control      2      62.7   114.6      Medio    2024-01-08
3       3        Control      3        NA    94.3       Bajo    2024-01-04
4       4        Control      4      65.7   101.8      Medio    2024-01-09
5       5        Control      5      66.3   104.4      Medio    2024-01-10
6       6 Fertilizante A      1      82.2    77.8       Bajo    2024-01-04
  indice_crecimiento categoria_peso log_peso
1          0.6366559           Bajo 4.535820
2          0.5471204           Bajo 4.741448
3                 NA           Bajo 4.546481
4          0.6453831           Bajo 4.623010
5          0.6350575           Bajo 4.648230
6          1.0565553           Bajo 4.354141

La creación de estas nuevas variables permite enriquecer el análisis y adaptar los datos a diferentes necesidades analíticas. Por ejemplo, la transformación logarítmica es especialmente útil cuando se requiere normalizar distribuciones asimétricas para análisis paramétricos, mientras que la categorización facilita la comparación entre grupos.

10.3.2 Recodificación de variables categóricas

La recodificación de variables categóricas es fundamental para establecer un orden específico en los niveles de los factores o para simplificar categorías, lo cual es particularmente relevante en análisis como ANOVA o regresión logística:

# Recodificar los niveles de daño por plaga como valores numéricos 
## factor() permite especificar el orden de los niveles 
## y asignar nuevas etiquetas
datos_cultivo$nivel_daño <- factor(datos_cultivo$daño_plaga, 
                                  levels = c("Bajo", "Medio", "Alto"), 
                                  labels = c("1", "2", "3"))

# Crear una variable indicadora (dummy) para el tratamiento control
# Esta transformación es útil para análisis de regresión
datos_cultivo$es_control <- 
  ifelse(datos_cultivo$tratamiento == "Control", 1, 0)

# Verificar la recodificación
head(datos_cultivo)
  parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
1       1        Control      1      59.4    93.3      Medio    2024-01-10
2       2        Control      2      62.7   114.6      Medio    2024-01-08
3       3        Control      3        NA    94.3       Bajo    2024-01-04
4       4        Control      4      65.7   101.8      Medio    2024-01-09
5       5        Control      5      66.3   104.4      Medio    2024-01-10
6       6 Fertilizante A      1      82.2    77.8       Bajo    2024-01-04
  indice_crecimiento categoria_peso log_peso nivel_daño es_control
1          0.6366559           Bajo 4.535820          2          1
2          0.5471204           Bajo 4.741448          2          1
3                 NA           Bajo 4.546481          1          1
4          0.6453831           Bajo 4.623010          2          1
5          0.6350575           Bajo 4.648230          2          1
6          1.0565553           Bajo 4.354141          1          0

La función factor() es especialmente útil en este contexto, ya que permite no solo recodificar los valores, sino también establecer un orden específico en los niveles de la variable categórica. Esto es crucial en análisis donde el orden de los niveles afecta la interpretación de los resultados, como en el caso de variables ordinales.

10.4 Ordenamiento y agrupamiento de datos

El ordenamiento y agrupamiento de datos constituyen operaciones fundamentales en el análisis exploratorio de datos, facilitando la identificación de patrones, la detección de valores atípicos y el cálculo de estadísticas descriptivas por grupos. Estas operaciones son especialmente relevantes en la estadística clásica, donde la estructura y organización de los datos influyen directamente en la calidad de los análisis posteriores (Wickham & Grolemund, 2017; R Core Team, 2023).

10.4.1 Ordenamiento de datos

R proporciona herramientas eficientes para ordenar datos mediante la función order(), que genera índices de ordenamiento que pueden aplicarse a las filas del data frame. Este ordenamiento puede realizarse por una o múltiples variables, en orden ascendente o descendente.

# Ordenar el data frame por altura de manera ascendente
# order() genera índices basados en los valores de altura_cm
# Los índices se utilizan para reordenar todas las filas 
datos_ordenados <- datos_cultivo[order(datos_cultivo$altura_cm), ]

# Verificar el ordenamiento mostrando las primeras filas
head(datos_ordenados)
   parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
18      18 Fertilizante C      3      45.3      NA       Alto    2024-01-11
8        8 Fertilizante A      3      52.3   123.8       Alto    2024-01-04
9        9 Fertilizante A      4      58.1    91.5      Medio    2024-01-08
1        1        Control      1      59.4    93.3      Medio    2024-01-10
20      20 Fertilizante C      5      60.3   110.5       Alto    2024-01-11
10      10 Fertilizante A      5      60.5   151.3      Medio    2024-01-07
   indice_crecimiento categoria_peso log_peso nivel_daño es_control
18                 NA           <NA>       NA          3          0
8           0.4224556           Alto 4.818667          3          0
9           0.6349727           Bajo 4.516339          2          0
1           0.6366559           Bajo 4.535820          2          1
20          0.5457014           Bajo 4.705016          3          0
10          0.3998678           Alto 5.019265          2          0

En este ejemplo, la función order(datos_cultivo$altura_cm) genera un vector de índices que indica el orden en el que deben organizarse las filas del data frame datos_cultivo para que la columna altura_cm quede ordenada de manera ascendente. Estos índices se utilizan para reordenar las filas del data frame, y el resultado se almacena en datos_ordenados. La función head() muestra las primeras filas del data frame ordenado para verificar el resultado.

# Ordenar por múltiples criterios: 
# Por tratamiento y por peso descendente
datos_ordenados_multi <- datos_cultivo[order(
  datos_cultivo$tratamiento,
  -datos_cultivo$peso_gr), ]

# Verificar el ordenamiento múltiple
head(datos_ordenados_multi)
   parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
2        2        Control      2      62.7   114.6      Medio    2024-01-08
5        5        Control      5      66.3   104.4      Medio    2024-01-10
4        4        Control      4      65.7   101.8      Medio    2024-01-09
3        3        Control      3        NA    94.3       Bajo    2024-01-04
1        1        Control      1      59.4    93.3      Medio    2024-01-10
10      10 Fertilizante A      5      60.5   151.3      Medio    2024-01-07
   indice_crecimiento categoria_peso log_peso nivel_daño es_control
2           0.5471204           Bajo 4.741448          2          1
5           0.6350575           Bajo 4.648230          2          1
4           0.6453831           Bajo 4.623010          2          1
3                  NA           Bajo 4.546481          1          1
1           0.6366559           Bajo 4.535820          2          1
10          0.3998678           Alto 5.019265          2          0

En este caso, se realiza un ordenamiento por múltiples criterios. Primero, se ordena por la columna tratamiento de manera ascendente (orden alfabético). Luego, dentro de cada grupo de tratamiento, se ordena por la columna peso_gr de manera descendente. El signo negativo - delante de datos_cultivo$peso_gr indica que el ordenamiento debe ser descendente para esta variable.

El ordenamiento por múltiples variables es particularmente útil cuando se necesita establecer una jerarquía en la organización de los datos, como por ejemplo, ordenar primero por tratamiento y luego por una variable de respuesta.

10.4.2 Cálculo de estadísticas por grupo

El análisis por grupos es esencial en la estadística experimental, permitiendo comparar tratamientos y evaluar la variabilidad dentro y entre grupos. R ofrece varias funciones para realizar estos cálculos:

# Calcular medias por tratamiento usando tapply
# tapply aplica la función mean a cada subconjunto definido por tratamiento
medias_altura <- tapply(datos_cultivo$altura_cm, 
                       datos_cultivo$tratamiento, 
                       mean, 
                       na.rm = TRUE)

La salida muestra las medias de altura para cada tratamiento:

# Mostrar las medias por tratamiento
print(medias_altura)
       Control Fertilizante A Fertilizante B Fertilizante C 
        63.525         64.540         70.225         66.100 

Para un análisis más completo, se pueden calcular múltiples estadísticas simultáneamente utilizando la función aggregate():

# Calcular media y desviación estándar por tratamiento
# aggregate permite trabajar con múltiples variables y funciones
estadisticas_grupo <- aggregate(cbind(altura_cm, peso_gr) ~ tratamiento, 
                               data = datos_cultivo, 
                               FUN = function(x) 
                                 c(media = mean(x, na.rm = TRUE), 
                                   sd = sd(x, na.rm = TRUE)))

Los resultados muestran estadísticas descriptivas por tratamiento:

# Mostrar los resultados del análisis por grupo
print(estadisticas_grupo)
     tratamiento altura_cm.media altura_cm.sd peso_gr.media peso_gr.sd
1        Control       63.525000     3.168990    103.525000   8.773967
2 Fertilizante A       63.275000    13.077812    111.100000  33.017066
3 Fertilizante B       70.225000     4.823812    131.925000  13.978406
4 Fertilizante C       71.300000     9.268945    123.475000  13.976021

Esta salida proporciona una visión completa de la variabilidad en las mediciones de altura y peso para cada tratamiento, revelando que:

  1. El Fertilizante B y C muestran las mayores medias en altura

  2. El Fertilizante A presenta la mayor variabilidad en altura (SD = 13.08)

  3. Los tratamientos con fertilizantes muestran mayores pesos medios que el control

Estos resultados preliminares son fundamentales para guiar análisis estadísticos más detallados, como ANOVA o comparaciones múltiples, y para identificar posibles patrones o anomalías en los datos experimentales (R Core Team, 2023).

La combinación de técnicas de ordenamiento y agrupamiento proporciona una base sólida para la exploración inicial de datos experimentales, permitiendo identificar patrones, detectar valores atípicos y generar hipótesis para análisis posteriores. Esta preparación cuidadosa de los datos es esencial para garantizar la validez y robustez de las conclusiones estadísticas.

10.5 Manejo de valores faltantes y duplicados

El tratamiento adecuado de valores faltantes y registros duplicados constituye un paso fundamental en la preparación de datos para análisis estadísticos. Esta etapa es crucial para garantizar la validez de los resultados y evitar sesgos en las estimaciones estadísticas. Los valores faltantes pueden afectar significativamente los análisis si no se manejan apropiadamente, mientras que los duplicados pueden inflar artificialmente el tamaño de la muestra y distorsionar las conclusiones (Wickham & Grolemund, 2017; R Core Team, 2023).

10.5.1 Identificación y manejo de valores faltantes

En R, existen diversas herramientas para identificar y tratar los valores faltantes (NA). La estrategia de manejo debe seleccionarse cuidadosamente según el contexto del estudio y el impacto potencial en los análisis posteriores:

# Realizar un diagnóstico inicial de valores faltantes por columna
# is.na() identifica valores NA en cada celda
# colSums() suma los valores TRUE (NA) en cada columna
na_por_columna <- colSums(is.na(datos_cultivo))

# Mostrar el resultado del diagnóstico
print(na_por_columna)
           parcela        tratamiento             bloque          altura_cm 
                 0                  0                  0                  2 
           peso_gr         daño_plaga      fecha_siembra indice_crecimiento 
                 2                  0                  0                  4 
    categoria_peso           log_peso         nivel_daño         es_control 
                 2                  2                  0                  0 

Este diagnóstico inicial permite identificar las variables más afectadas por valores faltantes y determinar la estrategia más apropiada para su tratamiento. Una vez identificados los valores faltantes, se pueden aplicar diferentes métodos de manejo:

# Eliminar filas que contengan cualquier valor faltante
# na.omit() crea un nuevo data frame excluyendo filas con NA
datos_completos <- na.omit(datos_cultivo)

# Imputar valores faltantes utilizando la media de la variable
# Este método es común pero debe usarse con precaución
datos_cultivo$altura_cm[is.na(datos_cultivo$altura_cm)] <- 
  mean(datos_cultivo$altura_cm, na.rm = TRUE)

# Verificar el resultado de la imputación
summary(datos_cultivo$altura_cm)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  45.30   60.45   66.06   66.01   69.70   82.90 

La eliminación de filas con valores faltantes (caso completo) es una solución simple pero puede resultar en pérdida significativa de información. La imputación con la media es una alternativa común, aunque puede subestimar la variabilidad real de los datos. En estudios más rigurosos, se pueden considerar métodos de imputación más sofisticados basados en modelos estadísticos.

10.5.2 Identificación y manejo de duplicados

Los registros duplicados pueden surgir por diversos motivos, desde errores en la entrada de datos hasta repeticiones intencionales en el diseño experimental. Su identificación y manejo apropiado es esencial para mantener la integridad del análisis:

# Identificar duplicados basados en variables específicas
# duplicated() evalúa si cada fila es una duplicación de una fila anterior
duplicados <- duplicated(datos_cultivo[, c("tratamiento", "bloque")])

# Analizar la presencia de duplicados
summary(duplicados)
   Mode   FALSE 
logical      20 
# Mostrar las filas duplicadas para su inspección
datos_cultivo[duplicados, ]
 [1] parcela            tratamiento        bloque             altura_cm         
 [5] peso_gr            daño_plaga         fecha_siembra      indice_crecimiento
 [9] categoria_peso     log_peso           nivel_daño         es_control        
<0 rows> (o 0- extensión row.names)
# Eliminar duplicados manteniendo la primera ocurrencia
# unique() conserva solo las filas únicas del data frame
datos_sin_duplicados <- unique(datos_cultivo)

# Verificar la reducción en el número de filas
nrow(datos_cultivo) - nrow(datos_sin_duplicados)
[1] 0

La identificación de duplicados puede realizarse considerando todas las variables o solo un subconjunto relevante para el análisis. Es importante distinguir entre duplicados verdaderos (errores) y repeticiones válidas en el diseño experimental.

10.5.3 Verificación de la integridad de los datos

Después de abordar los valores faltantes y duplicados, es crucial verificar la integridad general de los datos para asegurar la calidad y fiabilidad del análisis posterior. Esta verificación permite identificar posibles sesgos o inconsistencias introducidas durante el proceso de limpieza y transformación de los datos.

# Realizar un resumen estadístico completo
summary(datos_sin_duplicados)
    parcela      tratamiento            bloque    altura_cm        peso_gr     
 Min.   : 1.00   Length:20          Min.   :1   Min.   :45.30   Min.   : 77.8  
 1st Qu.: 5.75   Class :character   1st Qu.:2   1st Qu.:60.45   1st Qu.:102.5  
 Median :10.50   Mode  :character   Median :3   Median :66.06   Median :113.6  
 Mean   :10.50                      Mean   :3   Mean   :66.01   Mean   :117.5  
 3rd Qu.:15.25                      3rd Qu.:4   3rd Qu.:69.70   3rd Qu.:136.3  
 Max.   :20.00                      Max.   :5   Max.   :82.90   Max.   :151.3  
                                                                NA's   :2      
  daño_plaga        fecha_siembra        indice_crecimiento categoria_peso    
 Length:20          Min.   :2024-01-03   Min.   :0.3999     Length:20         
 Class :character   1st Qu.:2024-01-04   1st Qu.:0.5135     Class :character  
 Mode  :character   Median :2024-01-08   Median :0.5974     Mode  :character  
                    Mean   :2024-01-07   Mean   :0.5901                       
                    3rd Qu.:2024-01-10   3rd Qu.:0.6355                       
                    Max.   :2024-01-11   Max.   :1.0566                       
                                         NA's   :4                            
    log_peso     nivel_daño   es_control  
 Min.   :4.354   1:5        Min.   :0.00  
 1st Qu.:4.629   2:9        1st Qu.:0.00  
 Median :4.733   3:6        Median :0.00  
 Mean   :4.750              Mean   :0.25  
 3rd Qu.:4.915              3rd Qu.:0.25  
 Max.   :5.019              Max.   :1.00  
 NA's   :2                                

La función summary() proporciona un resumen estadístico de cada variable en el data frame datos_sin_duplicados. Este resumen incluye información como el mínimo, el primer cuartil, la mediana, la media, el tercer cuartil y el máximo para las variables numéricas, así como la frecuencia de cada categoría para las variables categóricas. La presencia de valores NA (Not Available) indica la cantidad de valores faltantes en cada variable.

# Verificar la estructura del data frame resultante
str(datos_sin_duplicados)
'data.frame':   20 obs. of  12 variables:
 $ parcela           : int  1 2 3 4 5 6 7 8 9 10 ...
 $ tratamiento       : chr  "Control" "Control" "Control" "Control" ...
 $ bloque            : int  1 2 3 4 5 1 2 3 4 5 ...
 $ altura_cm         : num  59.4 62.7 66 65.7 66.3 ...
 $ peso_gr           : num  93.3 114.6 94.3 101.8 104.4 ...
 $ daño_plaga        : chr  "Medio" "Medio" "Bajo" "Medio" ...
 $ fecha_siembra     : Date, format: "2024-01-10" "2024-01-08" ...
 $ indice_crecimiento: num  0.637 0.547 NA 0.645 0.635 ...
 $ categoria_peso    : chr  "Bajo" "Bajo" "Bajo" "Bajo" ...
 $ log_peso          : num  4.54 4.74 4.55 4.62 4.65 ...
 $ nivel_daño        : Factor w/ 3 levels "1","2","3": 2 2 1 2 2 1 1 3 2 2 ...
 $ es_control        : num  1 1 1 1 1 0 0 0 0 0 ...

La función str() muestra la estructura interna del data frame, incluyendo el tipo de cada variable (numérica, carácter, factor, fecha, etc.) y las primeras observaciones. Esta función es útil para confirmar que las variables tienen el tipo de dato esperado y que no hay errores en la importación o transformación de los datos.

# Calcular el porcentaje de datos completos por variable
porcentaje_completos <- colMeans(!is.na(datos_sin_duplicados)) * 100
print(porcentaje_completos)
           parcela        tratamiento             bloque          altura_cm 
               100                100                100                100 
           peso_gr         daño_plaga      fecha_siembra indice_crecimiento 
                90                100                100                 80 
    categoria_peso           log_peso         nivel_daño         es_control 
                90                 90                100                100 

En este bloque de código, se calcula el porcentaje de datos completos (no faltantes) para cada variable. La función is.na() devuelve un valor lógico (TRUE o FALSE) indicando si cada valor es faltante o no. El operador ! invierte estos valores lógicos, de modo que !is.na() devuelve TRUE para los valores no faltantes y FALSE para los valores faltantes. La función colMeans() calcula la media de estos valores lógicos por columna, lo que equivale al porcentaje de valores no faltantes. Finalmente, se multiplica por 100 para expresar el resultado como un porcentaje.

Esta verificación final permite asegurar que el tratamiento de valores faltantes y duplicados no ha introducido sesgos o inconsistencias en los datos. Es fundamental documentar todas las decisiones tomadas en este proceso, ya que pueden afectar la interpretación de los resultados posteriores.

La gestión adecuada de valores faltantes y duplicados es un paso crítico en la preparación de datos para análisis estadísticos. Las decisiones tomadas en esta etapa deben basarse en un entendimiento profundo del contexto del estudio y documentarse apropiadamente para garantizar la reproducibilidad del análisis (R Core Team, 2023).