11  Manipulación de datos con dplyr y tidyr

11.1 Introducción a los paquetes dplyr y tidyr

Los paquetes dplyr y tidyr constituyen componentes fundamentales del ecosistema tidyverse, diseñados específicamente para la manipulación y transformación eficiente de datos en R. Estos paquetes implementan una filosofía de programación que prioriza la claridad y consistencia en el código, facilitando el desarrollo de análisis estadísticos reproducibles (Wickham & Grolemund, 2017).

El paquete dplyr se especializa en la manipulación de datos tabulares, proporcionando un conjunto coherente de verbos (funciones) que corresponden a las operaciones más comunes en el análisis de datos. Estas operaciones incluyen el filtrado de observaciones, la selección de variables, la creación de nuevas variables y la agregación de datos. Por su parte, tidyr se centra en la reorganización estructural de los datos, permitiendo transformaciones entre diferentes formatos según los requerimientos específicos del análisis estadístico (Wickham et al., 2023).

11.2 Configuración del Entorno y Datos de Ejemplo

Se emplea el mismo conjunto de datos simulado del experimento agrícola utilizado en el capítulo anterior, lo que permite comparar directamente los enfoques de R base y tidyverse.

# Configuración inicial del entorno de análisis
library(dplyr)    # Carga del paquete para manipulación de datos
library(tidyr)    # Carga del paquete para reorganización de datos

# Creación de datos simulados para experimento agrícola
set.seed(123)     # Establecimiento de semilla para reproducibilidad

datos_cultivo <- data.frame(
    parcela = 1:20,    # Identificador único de cada parcela
    tratamiento = rep(c("Control", "Fertilizante A",
                       "Fertilizante B", "Fertilizante C"), each = 5),
    bloque = rep(1:5, times = 4),    # Estructura de bloques
     # Variable respuesta 1
    altura_cm = round(rnorm(20, mean = 65, sd = 10), 1),
     # Variable respuesta 2
    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)
)

# Introducción de valores faltantes para ejemplos didácticos
datos_cultivo$altura_cm[c(3, 15)] <- NA
datos_cultivo$peso_gr[c(7, 18)] <- NA

El conjunto de datos simulado representa un experimento agrícola con un diseño de bloques completamente aleatorizado. Los datos incluyen mediciones de altura y peso de plantas bajo diferentes tratamientos de fertilización, organizados en bloques para controlar la variabilidad ambiental. La estructura del experimento sigue los principios fundamentales del diseño experimental descritos por Montgomery et al. (2012), donde el control local mediante bloques permite una estimación más precisa de los efectos de los tratamientos.

Las variables incluidas en el conjunto de datos son:

  1. parcela: Identificador único de cada unidad experimental

  2. tratamiento: Factor experimental con cuatro niveles (Control y tres tipos de fertilizantes)

  3. bloque: Factor de control local con cinco niveles

  4. altura_cm: Variable respuesta que mide el crecimiento vertical de las plantas

  5. peso_gr: Variable respuesta que mide la biomasa de las plantas

  6. daño_plaga: Evaluación categórica del daño por plagas

  7. fecha_siembra: Registro temporal de la implementación del experimento

La inclusión deliberada de valores faltantes en las variables de respuesta (altura_cm y peso_gr) permite ilustrar técnicas comunes de manejo de datos incompletos, una situación frecuente en experimentos agrícolas (Field, 2013).

11.3 Operaciones básicas con dplyr

11.3.1 Filtrado de datos con filter()

La función filter() permite seleccionar subconjuntos de filas en un data frame o tibble, basándose en una o más condiciones lógicas. Esta función es esencial para enfocar el análisis en observaciones específicas que cumplen con criterios predefinidos (Wickham & Grolemund, 2017).

# Sintaxis general de la función filter()
filter(.data, ...)

Donde:

  1. .data: Especifica el data frame o tibble sobre el cual se aplicará el filtrado.

  2. : Representa una o más expresiones lógicas que deben evaluarse como TRUE para que una fila sea seleccionada.

Ejemplos:

# Ejemplo 1: Filtrar parcelas con tratamiento "Control"
datos_control <- filter(datos_cultivo, tratamiento == "Control")
head(datos_control) # Visualizar las primeras filas del resultado
  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 ejemplo, se crea un nuevo data frame llamado datos_control que contiene únicamente las filas donde la columna tratamiento es igual a “Control”. La función head() se utiliza para mostrar las primeras filas del resultado, permitiendo una rápida verificación del filtrado.

# Ejemplo 2: Filtrar parcelas con altura mayor a 65 cm y 
           # tratamiento distinto de "Control"
datos_altos <- filter(datos_cultivo, 
                      altura_cm > 65, tratamiento != "Control")
head(datos_altos) # Visualizar las primeras filas del resultado
  parcela    tratamiento bloque altura_cm peso_gr daño_plaga fecha_siembra
1       6 Fertilizante A      1      82.2    77.8       Bajo    2024-01-04
2       7 Fertilizante A      2      69.6      NA       Bajo    2024-01-08
3      11 Fertilizante B      1      77.2   130.7       Alto    2024-01-11
4      12 Fertilizante B      2      68.6   112.6      Medio    2024-01-06
5      13 Fertilizante B      3      69.0   142.4       Alto    2024-01-06
6      14 Fertilizante B      4      66.1   142.0       Alto    2024-01-09

En este caso, se combinan dos condiciones lógicas: la altura debe ser mayor a 65 cm y el tratamiento no debe ser “Control”. El resultado es un data frame que contiene solo las parcelas que cumplen ambos criterios. Es importante notar que, a diferencia de R base, no es necesario repetir el nombre del data frame en cada condición, lo que simplifica la sintaxis y mejora la legibilidad del código (Wickham et al., 2023).

11.3.2 Selección de columnas con select()

La función select() permite extraer un subconjunto de columnas de un data frame o tibble. Esta función es útil para simplificar el análisis, enfocándose únicamente en las variables relevantes para la investigación (Wickham & Grolemund, 2017).

# Sintaxis general de la función select()
select(.data, ...)

Donde:

  1. .data: Especifica el data frame o tibble de entrada.

  2. : Representa los nombres de las columnas a seleccionar, o funciones auxiliares que permiten patrones de selección más complejos.

Ejemplos:

# Ejemplo 1: Seleccionar las columnas altura_cm y peso_gr
datos_mediciones <- select(datos_cultivo, altura_cm, peso_gr)
head(datos_mediciones) # Visualizar las primeras filas del resultado
  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 ejemplo, se crea un nuevo data frame llamado datos_mediciones que contiene únicamente las columnas altura_cm y peso_gr del data frame original.

# Ejemplo 2: Excluir la columna fecha_siembra
datos_sin_fecha <- select(datos_cultivo, -fecha_siembra)
head(datos_sin_fecha) # Visualizar las primeras filas del resultado
  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

En este caso, se utiliza el operador - para excluir la columna fecha_siembra del resultado. El nuevo data frame datos_sin_fecha contiene todas las columnas del original, excepto la columna excluida.

# Ejemplo 3: Seleccionar columnas que terminan en "cm" o "gr"
datos_numericos <- select(datos_cultivo, ends_with("cm"), ends_with("gr"))
head(datos_numericos) # Visualizar las primeras filas del resultado
  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

Este ejemplo demuestra el uso de la función auxiliar ends_with() para seleccionar columnas cuyos nombres terminan con “cm” o “gr”. El resultado es un data frame que contiene únicamente las columnas que cumplen con este patrón. El uso de funciones auxiliares permite seleccionar columnas de manera flexible, lo que resulta útil en bases de datos extensas (Wickham et al., 2023).

11.3.3 Creación y transformación de variables con mutate()

La función mutate() permite crear nuevas columnas o modificar las existentes en un data frame o tibble. Esta función es fundamental para la ingeniería de variables, que consiste en transformar los datos originales para generar nuevas variables que capturen información relevante para el análisis (Wickham & Grolemund, 2017).

# Sintaxis general de la función mutate()
mutate(.data, ...)

Donde:

  1. .data: Especifica el data frame o tibble de entrada.

  2. : Representa una o más expresiones que definen las nuevas columnas o transformaciones.

Ejemplos:

# Ejemplo 1: Crear una nueva variable: índice de crecimiento
datos_cultivo <- mutate(datos_cultivo,
                       indice_crecimiento = 
                         altura_cm / peso_gr)

En este ejemplo, se crea una nueva columna llamada indice_crecimiento que se calcula como la razón entre la altura y el peso de cada planta. La nueva columna se añade al data frame original datos_cultivo.

# Ejemplo 2: Crear varias variables nuevas
datos_cultivo <- mutate(datos_cultivo,
                       altura_m = altura_cm / 100,
                       peso_kg = peso_gr / 1000,
                       categoria_altura = ifelse(
                         altura_cm > 65, "Alto", "Bajo"))

En este caso, se crean tres nuevas columnas: altura_m (altura en metros), peso_kg (peso en kilogramos) y categoria_altura (categoría de altura basada en un umbral). La función ifelse(condición, valor_si_verdadero, valor_si_falso) permite crear variables categóricas a partir de condiciones lógicas, lo que es común en la estadística clásica para definir grupos o categorías (Wickham & Grolemund, 2017).

11.3.4 Agrupamiento y resumen con group_by() y summarize()

Las funciones group_by() y summarize() son herramientas poderosas para el análisis exploratorio de datos y la generación de estadísticas descriptivas por grupos. La función group_by() permite dividir un data frame en grupos basados en los valores de una o más variables, mientras que summarize() calcula estadísticas resumen para cada grupo (Wickham & Grolemund, 2017).

# Sintaxis general de las funciones group_by() y summarize()
group_by(.data, ...)
summarize(.data, ...)

Donde:

  1. .data: Especifica el data frame o tibble de entrada.

  2. : Representa las variables de agrupamiento (en group_by()) o las expresiones de resumen (en summarize()).

Ejemplos:

# Ejemplo: Agrupar por tratamiento y calcular estadísticas descriptivas
resumen_tratamiento <- datos_cultivo %>%
    group_by(tratamiento) %>%
    summarize(
        media_altura = mean(altura_cm, na.rm = TRUE),
        sd_altura = sd(altura_cm, na.rm = TRUE),
        n = n()
    )
resumen_tratamiento
# A tibble: 4 × 4
  tratamiento    media_altura sd_altura     n
  <chr>                 <dbl>     <dbl> <int>
1 Control                63.5      3.17     5
2 Fertilizante A         64.5     11.7      5
3 Fertilizante B         70.2      4.82     5
4 Fertilizante C         66.1     14.1      5

En este ejemplo, se utiliza el operador pipe (%>%) para encadenar las funciones group_by() y summarize(). Primero, se agrupan los datos por la variable tratamiento. Luego, para cada grupo, se calculan las siguientes estadísticas:

  1. media_altura = mean(altura_cm, na.rm = TRUE): Calcula la media de la altura, excluyendo los valores faltantes (NA). El argumento na.rm = TRUE es crucial para evitar que los valores faltantes afecten el cálculo de la media.

  2. sd_altura = sd(altura_cm, na.rm = TRUE): Calcula la desviación estándar de la altura, también excluyendo los valores faltantes.

  3. n = n(): Cuenta el número de observaciones en cada grupo. La función n() es una función especial de dplyr que cuenta el tamaño de cada grupo.

El resultado es un nuevo data frame llamado resumen_tratamiento que contiene las estadísticas descriptivas para cada tratamiento. Estas funciones son esenciales para obtener resúmenes estadísticos por grupo, como promedios por tratamiento en un experimento clásico (Wickham et al., 2023).

11.3.5 Ordenamiento de datos con arrange()

La función arrange() permite ordenar las filas de un data frame o tibble según los valores de una o más variables. El ordenamiento es útil para identificar valores extremos, preparar tablas para reportes o facilitar la visualización de datos (Wickham & Grolemund, 2017).

# Sintaxis general de la función arrange()
arrange(.data, ...)

Donde:

  1. .data: Especifica el data frame o tibble de entrada.

  2. : Representa las variables por las que se desea ordenar. Se puede utilizar la función desc() para ordenar en orden descendente.

Ejemplos

# Ejemplo 1: Ordenar por altura de menor a mayor
datos_ordenados <- arrange(datos_cultivo, altura_cm)

En este ejemplo, se crea un nuevo data frame llamado datos_ordenados que contiene las mismas filas que datos_cultivo, pero ordenadas de menor a mayor según los valores de la columna altura_cm.

# Ejemplo 2: Ordenar por tratamiento y peso descendente
datos_ordenados_multi <- arrange(datos_cultivo, 
                                 tratamiento, 
                                 desc(peso_gr))

En este caso, se ordenan los datos por dos variables: primero por tratamiento (en orden ascendente por defecto) y luego por peso_gr (en orden descendente, gracias a la función desc()). El resultado es un data frame donde las filas están ordenadas alfabéticamente por tratamiento, y dentro de cada tratamiento, las filas están ordenadas de mayor a menor según el peso.

11.4 Introducción a los pipes (%>%)

El operador pipe (%>%), introducido por el paquete magrittr y adoptado como parte fundamental del tidyverse, representa una innovación significativa en la sintaxis de R. Este operador permite construir secuencias de operaciones de manera clara y lógica, siguiendo un flujo natural de procesamiento de datos. El pipe toma el resultado de una expresión a su izquierda y lo pasa como primer argumento a la función a su derecha (Wickham & Grolemund, 2017).

La sintaxis básica del operador pipe es:

# Estructura usando pipes
datos %>% funcion()

# Equivalente a la siguiente estructura anidada
funcion(datos)

11.4.1 Ventajas del uso de pipes

El uso de pipes ofrece múltiples ventajas en el análisis estadístico (Wickham et al., 2023):

  1. Legibilidad mejorada: Las operaciones se leen de izquierda a derecha y de arriba hacia abajo, siguiendo el orden natural de lectura. Esto facilita la comprensión del flujo de trabajo y reduce la probabilidad de errores.

  2. Reducción de objetos intermedios: No es necesario crear variables temporales para almacenar resultados intermedios. Esto simplifica el código y reduce el riesgo de errores asociados con la gestión de múltiples objetos.

  3. Facilidad de depuración: Cada paso puede ser comentado o modificado independientemente. Esto facilita la identificación y corrección de errores en el código.

  4. Claridad en la secuencia de operaciones: El flujo de trabajo se hace explícito y fácil de seguir. Esto mejora la mantenibilidad del código y facilita la colaboración entre analistas.

11.4.2 Ejemplo práctico

Para ilustrar las ventajas del uso de pipes, consideremos el siguiente ejemplo, donde se calcula la media de la altura por tratamiento, excluyendo los valores faltantes:

Sin pipe (anidado): En la sintaxis tradicional, las funciones deben anidarse, lo que puede dificultar la lectura:

# Calcular la media de altura por tratamiento, excluyendo valores NA
resumen_tratamiento <- summarize(
  group_by(
    filter(datos_cultivo, !is.na(altura_cm)),
    tratamiento
  ),
  media_altura = mean(altura_cm)
)

En este ejemplo, primero se filtran las filas sin valores faltantes en altura_cm, luego se agrupan por tratamiento y finalmente se calcula la media de altura para cada grupo. La anidación de funciones dificulta la lectura y comprensión del código.

Con pipe (más legible): El mismo análisis, usando pipes, resulta más claro y fácil de seguir:

# Calcular la media de altura por tratamiento, excluyendo valores NA
resumen_tratamiento <- datos_cultivo %>%
    # 1. Eliminar filas con NA en altura_cm
    filter(!is.na(altura_cm)) %>%    
    # 2. Agrupar los datos por tratamiento
    group_by(tratamiento) %>%    
    # 3. Calcular la media de altura por grupo
    summarize(media_altura = mean(altura_cm))

En este ejemplo, el código se lee de arriba hacia abajo, siguiendo el orden lógico de las operaciones:

  1. En la primera línea, se eliminan las filas donde la altura es NA.

  2. En la segunda línea, se agrupan los datos por el tipo de tratamiento.

  3. En la tercera línea, se calcula la media de la altura para cada tratamiento.

Cada paso es explícito y se puede leer de arriba hacia abajo, lo que facilita la comprensión y depuración del análisis (Wickham & Grolemund, 2017). El uso de pipes mejora significativamente la legibilidad y mantenibilidad del código, facilitando la colaboración y reduciendo la probabilidad de errores.

11.5 Transformaciones de datos con tidyr

El paquete tidyr es una herramienta fundamental para la reorganización y transformación de datos en R, permitiendo adaptar la estructura de los conjuntos de datos a los requerimientos de los métodos estadísticos clásicos. Estas transformaciones son esenciales para preparar los datos antes de aplicar técnicas como ANOVA, regresión o análisis descriptivos, ya que muchos procedimientos requieren que los datos estén en un formato específico (Wickham & Grolemund, 2017).

11.5.1 Transformación de formato ancho a largo con pivot_longer()

La función pivot_longer() convierte varias columnas de un data frame en pares de nombre-valor, generando un formato largo. Este formato es especialmente útil en análisis estadísticos donde cada observación debe ocupar una fila y las variables medidas se representan en una columna adicional, como en el caso de ANOVA de medidas repetidas (Wickham & Grolemund, 2017).

La sintaxis principal es:

# Sintaxis principal de la funcion pivot_longer ()
pivot_longer(
  data,              # Data frame o tibble de entrada
  cols,              # Columnas a transformar
  # Nombre de la nueva columna para las columnas originales
  names_to = "name", 
  # Nombre de la nueva columna para los valores originales
  values_to = "value" 
)

Para ilustrar el uso de pivot_longer(), consideremos un ejemplo simplificado:

# Crear un data frame de ejemplo
datos_ancho <- data.frame(
  parcela = 1:3,
  altura_2023 = c(150, 160, 155),
  peso_2023 = c(80, 85, 82),
  altura_2024 = c(165, 170, 168),
  peso_2024 = c(88, 90, 89)
)

datos_ancho
  parcela altura_2023 peso_2023 altura_2024 peso_2024
1       1         150        80         165        88
2       2         160        85         170        90
3       3         155        82         168        89

Este data frame representa mediciones de altura y peso de tres parcelas en dos años diferentes. Para transformar este data frame a formato largo, podemos usar pivot_longer() de la siguiente manera:

# Transformar a formato largo
datos_largo <- datos_ancho %>%
  pivot_longer(
    cols = c(altura_2023, peso_2023, altura_2024, peso_2024),
    names_to = "variable",
    values_to = "valor"
  )

datos_largo
# A tibble: 12 × 3
   parcela variable    valor
     <int> <chr>       <dbl>
 1       1 altura_2023   150
 2       1 peso_2023      80
 3       1 altura_2024   165
 4       1 peso_2024      88
 5       2 altura_2023   160
 6       2 peso_2023      85
 7       2 altura_2024   170
 8       2 peso_2024      90
 9       3 altura_2023   155
10       3 peso_2023      82
11       3 altura_2024   168
12       3 peso_2024      89

En este ejemplo:

  1. cols = c(altura_2023, peso_2023, altura_2024, peso_2024): Especifica las columnas que se van a transformar.

  2. names_to = “variable”: Indica que los nombres de las columnas originales se almacenarán en una nueva columna llamada “variable”.

  3. values_to = “valor”: Indica que los valores de las columnas originales se almacenarán en una nueva columna llamada “valor”.

El resultado es un data frame en formato largo, donde cada fila representa una medición de altura o peso para una parcela en un año específico. Este formato es ideal para realizar análisis estadísticos que requieren que cada observación ocupe una fila, como ANOVA de medidas repetidas o modelos mixtos (Kutner et al., 2005).

11.5.2 Transformación de formato largo a ancho con pivot_wider()

La función pivot_wider() realiza la operación inversa a pivot_longer(), transformando un data frame de formato largo a formato ancho. Esta función es útil cuando se necesita organizar los datos de manera que diferentes valores de una variable se conviertan en columnas separadas, facilitando la comparación entre grupos o condiciones (Wickham & Grolemund, 2017).

La sintaxis principal es:

# Sintaxis principal de la funcion pivot_wider ()
pivot_wider(
  # Data frame o tibble de entrada
  data,              
  # Columna cuyos valores se usarán como nombres de las nuevas columnas
  names_from = , 
  # Columna cuyos valores se usarán para llenar las nuevas columnas
  values_from =        
)

Para ilustrar el uso de pivot_wider(), consideremos el data frame datos_largo creado en la sección anterior. Para transformar este data frame de nuevo a formato ancho, podemos usar pivot_wider() de la siguiente manera:

# Transformar a formato ancho
datos_ancho <- datos_largo %>%
  pivot_wider(
    names_from = variable,
    values_from = valor
  )

datos_ancho
# A tibble: 3 × 5
  parcela altura_2023 peso_2023 altura_2024 peso_2024
    <int>       <dbl>     <dbl>       <dbl>     <dbl>
1       1         150        80         165        88
2       2         160        85         170        90
3       3         155        82         168        89

En este ejemplo:

  1. names_from = variable: Especifica que los valores de la columna variable (altura_2023, peso_2023, altura_2024, peso_2024) se utilizarán como nombres de las nuevas columnas.

  2. values_from = valor: Especifica que los valores de la columna valor se utilizarán para llenar las nuevas columnas.

El resultado es un data frame en formato ancho, donde cada fila representa una parcela y cada columna representa una medición de altura o peso en un año específico. Este formato facilita la comparación directa de las mediciones entre años para cada parcela.

11.5.3 Separación y Unión de Columnas con separate() y unite()

Las funciones separate() y unite() permiten manipular variables compuestas, dividiendo una columna en varias o combinando varias columnas en una sola. Estas funciones son útiles para limpiar y estructurar datos que contienen información combinada en una sola columna (Wickham & Grolemund, 2017).

La función separate() divide una columna en varias, utilizando un carácter separador. Su sintaxis principal es:

# Sintaxis de la funcion separate ()
separate(
  data,    # Data frame o tibble de entrada
  col,     # Columna a dividir
  into,    # Vector con los nombres de las nuevas columnas
  sep      # Carácter separador 
)

Por ejemplo, considérese el siguiente subconjunto:

# Crear el dataframe para el ejemplo
mini_datos_comp <- data.frame(
  parcela_bloque = c("1-1", "2-2", "3-3"),
  altura_cm = c(70, 65, 60)
)

mini_datos_comp
  parcela_bloque altura_cm
1            1-1        70
2            2-2        65
3            3-3        60

Para separar la columna parcela_bloque en dos columnas llamadas parcela y bloque, se utiliza:

mini_separado <- separate(
  data = mini_datos_comp,
  col = parcela_bloque,    # Columna a dividir
  into = c("parcela", "bloque"),# Nombres de las nuevas columnas
  sep = "-"                # Carácter separador
)

mini_separado
  parcela bloque altura_cm
1       1      1        70
2       2      2        65
3       3      3        60

El argumento col indica la columna a dividir, into define los nombres de las nuevas columnas y sep especifica el carácter separador (Wickham & Grolemund, 2017).

La función unite() combina dos o más columnas en una sola, utilizando un carácter separador. Su sintaxis principal es:

# Sintaxis de la funcion unite ()
unite(
  data,    # Data frame o tibble de entrada
  col,     # Nombre de la nueva columna
  ...,     # Columnas a unir
  sep      # Carácter separador
)

Por ejemplo, para volver a unir las columnas parcela y bloque en una sola columna parcela_bloque:

mini_unido <- unite(
  data = mini_separado,
  col = "parcela_bloque", # Nombre de la nueva columna
  parcela, bloque,        # Columnas a unir
  sep = "-"                # Carácter separador
)

mini_unido
  parcela_bloque altura_cm
1            1-1        70
2            2-2        65
3            3-3        60

El argumento col define el nombre de la nueva columna resultante, los siguientes argumentos son las columnas a unir y sep indica el carácter separador (Wickham & Grolemund, 2017).

11.6 Comparación entre la manipulación de datos con R base y tidyverse

La manipulación de datos constituye una etapa esencial en el análisis estadístico clásico, ya que permite preparar, transformar y explorar la información antes de aplicar técnicas inferenciales o modelos predictivos. En el entorno R, existen dos enfoques principales para realizar estas tareas: el uso de funciones base y el empleo de paquetes del tidyverse, como dplyr y tidyr. A continuación, se presenta una comparación estructurada de ambos enfoques, considerando aspectos clave como sintaxis, legibilidad, flexibilidad y reproducibilidad (Wickham & Grolemund, 2017).

Aspecto R base tidyverse (dplyr/tidyr)
Sintaxis Uso de corchetes, funciones como subset(), apply(), y anidación. Uso de funciones verbales (filter(), select(), mutate(), etc.) y pipes %>%.
Legibilidad El código puede ser difícil de leer, especialmente con operaciones anidadas. El flujo de trabajo es secuencial y fácil de seguir, cada paso en una línea.
Creación de variables Se usa $ o transform(). Se usa mutate(), que permite crear o modificar variables de forma clara.
Filtrado de filas Se usan corchetes o subset(). Se usa filter(), con sintaxis más intuitiva y sin necesidad de repetir el nombre del data frame.
Selección de columnas Se usan corchetes o select(). Se usa select(), con funciones auxiliares como starts_with(), ends_with().
Agrupamiento y resumen Se usan tapply(), aggregate(), o bucles. Se usan group_by() y summarize(), facilitando el cálculo de estadísticas por grupo.
Transformación de formato Se usan funciones como reshape(), melt(), cast(). Se usan pivot_longer() y pivot_wider(), con sintaxis más clara y moderna.
Manejo de variables compuestas Se requiere manipulación manual con funciones como strsplit(). Se usan separate() y unite(), que simplifican la división y combinación de columnas.
Reproducibilidad El código puede ser menos reproducible y más propenso a errores. El uso de pipes y funciones verbales mejora la reproducibilidad y la claridad del análisis.
Curva de aprendizaje Familiar para usuarios con experiencia previa en R, pero puede ser menos intuitivo para principiantes. Más accesible para principiantes, especialmente por la coherencia y claridad de la sintaxis.

En síntesis, el enfoque tidyverse ofrece ventajas notables en términos de claridad, reproducibilidad y facilidad de uso, especialmente en flujos de trabajo complejos o colaborativos. Sin embargo, el conocimiento de las funciones base de R sigue siendo valioso, ya que permite comprender el funcionamiento interno del lenguaje y resolver tareas específicas de manera eficiente (Wickham & Grolemund, 2017).