32  Manipulación de datos en R

Carguemos los paquetes

Code
library(palmerpenguins)
library(dplyr)
library(DT)
ImportantNota 1

En R y en Bash existe el comando head, que permite visualizar los primeros elementos de un objeto o archivo.
- En R: head(mi_vector) muestra los primeros valores de un vector o data frame.
- En Bash: head archivo.txt muestra las primeras líneas de un archivo de texto.
Esto es útil para inspeccionar rápidamente datos sin necesidad de abrir todo el contenido.

ImportantNota 2

En R (con dplyr) usamos el operador pipe %>% para encadenar funciones, cumple una función muy similar al pipe | en Bash.

Ambos operadores permiten construir flujos de trabajo claros y reproducibles.

En RStudio, pipe %>% se inserta rápido con:

  • Windows/Linux: Ctrl + Shift + M
  • iOS / Mac: Cmd + Shift + M
ImportantNota 3

En R podemos usar :: para indicar que una función proviene de un paquete específico.
- Ejemplo: dplyr::select() llama directamente a la función select del paquete dplyr.
- Esto evita conflictos cuando diferentes paquetes tienen funciones con el mismo nombre.
- Podemos cargar un paquete completo con library(dplyr) o usar solo una función con dplyr::función.

La manera correcta para evitar ambigüedades es usar siempre paquete::función cuando hay riesgo de conflicto.

TipTip

En este curso trabajaremos principalmente con dplyr y el operador %>%, ya que ofrece una sintaxis clara y didáctica para manipular data frames y tibbles.

Sin embargo, es importante saber que para datasets muy grandes existe el paquete data.table, que está optimizado para velocidad y eficiencia en memoria.

32.1 Paquete palmerpenguins

El objetivo de palmerpenguins es proporcionar un gran conjunto de datos para la exploración y visualización de datos, como alternativa a iris.

32.2 Acerca de los datos

Los datos fueron recopilados y puestos a disposición por la Dra. Kristen Gorman y la Estación Palmer, Antártida LTER , miembro de la Red de Investigación Ecológica a Largo Plazo.

32.3 Medidas de tamaño de pingüinos adultos en busca de alimento cerca de la Estación Palmer, Antártida

Una de ellas se llama penguins, y es una versión simplificada de los datos brutos; consulte ?penguinspara obtener más información:

Code
head(penguins) %>% 
  DT::datatable(rownames = FALSE)
  • species / especies: un factor que indica la especie de pingüino (Adelia, Barbijo y Gentoo)
  • island / isla: un factor que denota una isla en el archipiélago Palmer, Antártida (Biscoe, Dream o Torgersen)
  • bill_length_mm / longitud del pico en mm: un número que indica la longitud del pico (en milímetros)
  • bill_depth_mm / grosor del pico en mm: un número que indica la grosor del pico (milímetros)
  • flipper_length_mm / longitud de la aleta en mm: un número entero que indica la longitud de la aleta (en milímetros)
  • body_mass_g / masa corporal en gramos: un número entero que indica la masa corporal (gramos)
  • sex / sexo: un factor que indica el sexo del pingüino (hembra, macho)
  • year / año del estudio: un número entero que indica el año del estudio (2007, 2008 o 2009)

Información tomada de la página principal de palmerpenguins.

32.4 Tamaño, puesta y datos de isótopos sanguíneos de pingüinos adultos en busca de alimento cerca de la Estación Palmer, Antártida

El segundo conjunto de datos es penguins_raw, y contiene todas las variables y los nombres originales tal como se descargaron; consulte ?penguins_rawpara obtener más información.

Code
head(penguins_raw, 4) %>% 
  DT::datatable(rownames = FALSE)
  • studyName /nombre del estudio : Expedición de muestreo a partir de la cual se recopilaron, generaron, etc., datos.
  • Sample Number / Número de muestra un número entero que denota la secuencia de numeración continua para cada muestra.
  • Species/ Especies: una cadena de caracteres que denota la especie de pingüino.
  • Region/ Región: una cadena de caracteres que indica la región de la cuadrícula de muestreo de Palmer LTER.
  • Island / Isla: una cadena de caracteres que indica la isla cercana a la estación Palmer donde se recolectaron las muestras
  • Stage / Escenario: una cadena de caracteres que indica la etapa reproductiva en el momento de la toma de muestras
  • Individual ID / Identificación individual: una cadena de caracteres que indica el ID único de cada individuo en el conjunto de datos.
  • Clutch Completion / Finalización del embrague: una cadena de caracteres que indica si el nido estudiado se observó con una nidada completa, es decir, 2 huevos.
  • Date Egg / Fecha de muestreo del huevo: una fecha que indica la fecha en que se observó el nido estudiado con 1 huevo (muestreado).
  • Culmen Length / Longitud de la cresta dorsal: un número que indica la longitud de la cresta dorsal del pico de un ave (en milímetros)
  • Culmen Depth / Profundidad del culmen: un número que indica la profundidad de la cresta dorsal del pico de un ave (en milímetros)
  • Flipper Length/ Longitud de la aleta: un número entero que indica la longitud de la aleta del pingüino (en milímetros)
  • Body Mass/ Masa corporal: un número entero que indica la masa corporal del pingüino (en gramos)
  • Sex / Sexo: una cadena de caracteres que indica el sexo de un animal
  • Delta 15 N: un número que indica la medida de la proporción de isótopos estables 15N:14N
  • Delta 13 C: un número que indica la medida de la proporción de isótopos estables 13C:12C
  • Comments/ Comentarios: una cadena de caracteres con texto que proporciona información adicional relevante para los datos.

32.5 Revisar las dimensiones de un objeto

Función Descripción Ejemplo
length() Devuelve el número de elementos de un vector o lista. length(1:10) → 10
dim() Devuelve las dimensiones (filas, columnas) de matrices y data frames. dim(penguins) → 344 8
nrow() Número de filas de un objeto tipo data frame o matriz. nrow(penguins) → 344
ncol() Número de columnas de un objeto tipo data frame o matriz. ncol(penguins) → 8
str() Muestra la estructura del objeto, incluyendo dimensiones y tipo de datos. str(penguins)

Ambos conjuntos de datos contienen información sobre 344 pingüinos. Estos conjuntos de datos incluyen 3 especies diferentes de pingüinos, recopiladas en 3 islas del archipiélago Palmer, en la Antártida. Vamos a revisar la estructura de los datos:

Code
str(penguins)
tibble [344 × 8] (S3: tbl_df/tbl/data.frame)
 $ species          : Factor w/ 3 levels "Adelie","Chinstrap",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ island           : Factor w/ 3 levels "Biscoe","Dream",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ bill_length_mm   : num [1:344] 39.1 39.5 40.3 NA 36.7 39.3 38.9 39.2 34.1 42 ...
 $ bill_depth_mm    : num [1:344] 18.7 17.4 18 NA 19.3 20.6 17.8 19.6 18.1 20.2 ...
 $ flipper_length_mm: int [1:344] 181 186 195 NA 193 190 181 195 193 190 ...
 $ body_mass_g      : int [1:344] 3750 3800 3250 NA 3450 3650 3625 4675 3475 4250 ...
 $ sex              : Factor w/ 2 levels "female","male": 2 1 1 NA 1 2 1 2 NA NA ...
 $ year             : int [1:344] 2007 2007 2007 2007 2007 2007 2007 2007 2007 2007 ...
Tip¿Qué significa?
  • tibble → Es una versión moderna del data frame, creada por el paquete tibble/dplyr.

  • [344 × 8] → Son las dimensiones del objeto:

    • 344 filas → cada fila representa una observación o registro.

    • 8 columnas → cada columna representa una variable o atributo.

32.6 Funciones que vamos a emplear de dplyr

  • select() : Seleccionar nombres de las columnas. –> select(dataframe, columna1, columna2, … columnax)
  • filter() : Filtrar filas por una condicion especifica, apartir de la columna. –> filter(dataframe, columna1 == “condicion”)
  • mutate() : Modificar o agregar columnas. –> mutate(dataframe, columna1 = “condicion”)
  • group_by() : Agrupar informacion de acuerdo a un(as) columna(s) seleccionada(s).
  • if_else() : Condicional. –> if_else(dataframe, codicion, si se acepta entonces, si se rechaza entonces)
  • arrange() : Acomodar los resultados, default de menor a mayor.
  • count(): Cuenta los valores de acuerdo a una variable.
  • left_join() : Unir dos dataframe con base en una misma columna en comun. –> left_join(dataframe1, dataframe2, by = “Columna en comun, mismo nombre”)
  • n_distinct() : Cuenta las filas unicas.
  • distinct() : Muestra las filas duplicadas.
  • summarise() : reduce varios valores seleccionados en un resumen.

32.7 Manos a la obra

En el dataset penguins del paquete palmerpenguins se registran 3 especies de pingüinos:

  • Adelie
  • Chinstrap
  • Gentoo
  1. Podemos usar R base para identificar esta información:
Code
unique(penguins$species)
[1] Adelie    Gentoo    Chinstrap
Levels: Adelie Chinstrap Gentoo

Emplear las funciones del paquete dplyr:

  1. Usar distinct() para obtener los valores únicos de la columna species.
Code
penguins %>% 
  dplyr::select(species) %>% 
  distinct() # Nos da valores unicos, sin duplicaciones
# A tibble: 3 × 1
  species  
  <fct>    
1 Adelie   
2 Gentoo   
3 Chinstrap
  1. Usar n_distinct() para obtener el número de especies unicas.
Code
penguins %>% 
  dplyr::select(species) %>% 
  n_distinct()
[1] 3
  1. ¿Cuántos datos registrados tenemos por especies o número de individuos por especie?
Code
penguins %>% 
  count(species) 
# A tibble: 3 × 2
  species       n
  <fct>     <int>
1 Adelie      152
2 Chinstrap    68
3 Gentoo      124
  1. Número de individuos de cada sexo
Code
penguins %>% 
  count(sex) 
# A tibble: 3 × 2
  sex        n
  <fct>  <int>
1 female   165
2 male     168
3 <NA>      11
  1. ¿Cuántos hembras y machos hay de cada especie?
Code
penguins %>% 
  count(species, sex)
# A tibble: 8 × 3
  species   sex        n
  <fct>     <fct>  <int>
1 Adelie    female    73
2 Adelie    male      73
3 Adelie    <NA>       6
4 Chinstrap female    34
5 Chinstrap male      34
6 Gentoo    female    58
7 Gentoo    male      61
8 Gentoo    <NA>       5
  1. Número de individuos registrados en cada isla:
Code
penguins %>% 
  count(island)
# A tibble: 3 × 2
  island        n
  <fct>     <int>
1 Biscoe      168
2 Dream       124
3 Torgersen    52
  1. Número de individuos registrados en cada isla:
Code
penguins %>% 
  count(species, island, sex)
# A tibble: 13 × 4
   species   island    sex        n
   <fct>     <fct>     <fct>  <int>
 1 Adelie    Biscoe    female    22
 2 Adelie    Biscoe    male      22
 3 Adelie    Dream     female    27
 4 Adelie    Dream     male      28
 5 Adelie    Dream     <NA>       1
 6 Adelie    Torgersen female    24
 7 Adelie    Torgersen male      23
 8 Adelie    Torgersen <NA>       5
 9 Chinstrap Dream     female    34
10 Chinstrap Dream     male      34
11 Gentoo    Biscoe    female    58
12 Gentoo    Biscoe    male      61
13 Gentoo    Biscoe    <NA>       5

Crea una nueva columna llamada body_mass_kg que convierta el peso de gramos a kilogramos.

Code
penguins_kg <- penguins %>% 
  mutate(body_mass_kg = body_mass_g / 1000) 

head(penguins_kg)
# A tibble: 6 × 9
  species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
  <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
1 Adelie  Torgersen           39.1          18.7               181        3750
2 Adelie  Torgersen           39.5          17.4               186        3800
3 Adelie  Torgersen           40.3          18                 195        3250
4 Adelie  Torgersen           NA            NA                  NA          NA
5 Adelie  Torgersen           36.7          19.3               193        3450
6 Adelie  Torgersen           39.3          20.6               190        3650
# ℹ 3 more variables: sex <fct>, year <int>, body_mass_kg <dbl>

Calcula el promedio de masa corporal por especie.

Code
penguins_kg %>% 
  group_by(species) %>% 
  summarise(mean_mass_kg = mean(body_mass_kg, na.rm = TRUE))
# A tibble: 3 × 2
  species   mean_mass_kg
  <fct>            <dbl>
1 Adelie            3.70
2 Chinstrap         3.73
3 Gentoo            5.08

Crea una columna peso_categoria que indique "Ligero" si el pingüino pesa menos de 4000 g = 4kg y "Pesado" en caso contrario.

Code
penguins_kg <- penguins_kg %>% 
  mutate(peso_categoria = if_else(body_mass_kg < 4, "Ligero", "Pesado"))

head(penguins_kg)
# A tibble: 6 × 10
  species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
  <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
1 Adelie  Torgersen           39.1          18.7               181        3750
2 Adelie  Torgersen           39.5          17.4               186        3800
3 Adelie  Torgersen           40.3          18                 195        3250
4 Adelie  Torgersen           NA            NA                  NA          NA
5 Adelie  Torgersen           36.7          19.3               193        3450
6 Adelie  Torgersen           39.3          20.6               190        3650
# ℹ 4 more variables: sex <fct>, year <int>, body_mass_kg <dbl>,
#   peso_categoria <chr>

¿Cuántos pingüinos tenemos por categoría?

Code
penguins_kg %>% 
  count(peso_categoria)
# A tibble: 3 × 2
  peso_categoria     n
  <chr>          <int>
1 Ligero           165
2 Pesado           177
3 <NA>               2

Clasifica a los pingüinos en categorías según su masa corporal:

  • < 3500 g"Pequeño"
  • 3500–4500 g"Mediano"
  • > 4500 g"Grande"
Code
penguins_kg %>% 
  mutate(categoria = case_when(
    body_mass_g < 3500 ~ "Pequeño",
    body_mass_g >= 3500 & body_mass_g <= 4500 ~ "Mediano",
    body_mass_g > 4500 ~ "Grande"
  ))
# A tibble: 344 × 11
   species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
   <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
 1 Adelie  Torgersen           39.1          18.7               181        3750
 2 Adelie  Torgersen           39.5          17.4               186        3800
 3 Adelie  Torgersen           40.3          18                 195        3250
 4 Adelie  Torgersen           NA            NA                  NA          NA
 5 Adelie  Torgersen           36.7          19.3               193        3450
 6 Adelie  Torgersen           39.3          20.6               190        3650
 7 Adelie  Torgersen           38.9          17.8               181        3625
 8 Adelie  Torgersen           39.2          19.6               195        4675
 9 Adelie  Torgersen           34.1          18.1               193        3475
10 Adelie  Torgersen           42            20.2               190        4250
# ℹ 334 more rows
# ℹ 5 more variables: sex <fct>, year <int>, body_mass_kg <dbl>,
#   peso_categoria <chr>, categoria <chr>

Ordena los pingüinos por longitud del pico (bill_length_mm) de mayor a menor.

Code
penguins_kg %>% 
  arrange(desc(bill_length_mm)) %>%  # de mayor a menor
  # tambien se puede poner arrange(-bill_length_mm)
  head()
# A tibble: 6 × 10
  species   island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
  <fct>     <fct>           <dbl>         <dbl>             <int>       <int>
1 Gentoo    Biscoe           59.6          17                 230        6050
2 Chinstrap Dream            58            17.8               181        3700
3 Gentoo    Biscoe           55.9          17                 228        5600
4 Chinstrap Dream            55.8          19.8               207        4000
5 Gentoo    Biscoe           55.1          16                 230        5850
6 Gentoo    Biscoe           54.3          15.7               231        5650
# ℹ 4 more variables: sex <fct>, year <int>, body_mass_kg <dbl>,
#   peso_categoria <chr>

Si queremos que sea de menor a mayor, quitamos desc().

Code
penguins_kg %>% 
  arrange(bill_length_mm) %>%  # de menor a mayor
  head()
# A tibble: 6 × 10
  species island    bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
  <fct>   <fct>              <dbl>         <dbl>             <int>       <int>
1 Adelie  Dream               32.1          15.5               188        3050
2 Adelie  Dream               33.1          16.1               178        2900
3 Adelie  Torgersen           33.5          19                 190        3600
4 Adelie  Dream               34            17.1               185        3400
5 Adelie  Torgersen           34.1          18.1               193        3475
6 Adelie  Torgersen           34.4          18.4               184        3325
# ℹ 4 more variables: sex <fct>, year <int>, body_mass_kg <dbl>,
#   peso_categoria <chr>

Calcula el promedio y la desviación estándar de la longitud del ala (flipper_length_mm) por especie.

Code
penguins %>% 
  group_by(species) %>% 
  summarise(
    mean_flipper = mean(flipper_length_mm, na.rm = TRUE), #promedio
    sd_flipper = sd(flipper_length_mm, na.rm = TRUE) # desviacion estandar
  )
# A tibble: 3 × 3
  species   mean_flipper sd_flipper
  <fct>            <dbl>      <dbl>
1 Adelie            190.       6.54
2 Chinstrap         196.       7.13
3 Gentoo            217.       6.48