Listas en R

Introducción a R Estructuras de datos
Crea y manipula listas con la función list

¿Qué es una lista en R? Una lista es una colección ordenada de cualquier objeto de R. A diferencia de los vectores y las matrices, donde los elementos deben ser del mismo tipo, en el caso de las listas los elementos pueden ser de un tipo diferente o almacenar distintas estructuras.

Crear una lista en R

Si no sabes cómo crear una lista en R, solo necesitas usar la función list, especificando los objetos que deseas unir dentro de tu lista.

x <- c(45, 12, 56, 14, 16)
y <- c("Coche", "Bicicleta")
z <- matrix(1:12, ncol = 4)

# Creando una lista
mi_lista <- list(x, y, z)
mi_lista
[[1]]
[1] 45 12 56 14 16

[[2]]
[1] "Coche"  "Bicicleta"

[[3]]
      [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12

Nombrar elementos de listas en R

Como en otras estructuras de datos de R, puedes nombrar los elementos para identificar o tener un acceso más fácil a los objetos utilizando el signo $.

mi_lista_nombres <- list(A = x, B = y, C = z)
mi_lista_nombres
$`A`
[1] 45 12 56 14

$B
[1] "Coche"  "Bicicleta"

$C
      [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12

Extraer elementos de una lista en R

Ahora, vamos a indexar los elementos de la lista para acceder a los datos que queramos. Para ello, puedes extraer los elementos de la lista con corchetes simples o dobles.

# Primer elemento de la lista
mi_lista[1]

# Primer elemento de la lista, simplificando la salida
mi_lista[[1]]

# Primer elemento del primer elemento de la lista.
mi_lista[[1]][1]
unlist(mi_lista[1])[1] # Equivalente

# Primera columna del tercer elemento
mi_lista[[3]][, 1]

# Segundo elemento de la primera columna
# del tercer elemento de la lista
mi_lista[[3]][, 1][2]
mi_lista[[3]][2, 1] # Equivalente

Sin embargo, en caso de que hayas nombrado los elementos de tu lista, puedes usar la forma anterior para obtener los valores, especificar los nombres de los elementos de la lista a los que deseas acceder, o usar el operador $, tal y como se muestra en los siguientes ejemplos:

# Primer elemento de la lista
mi_lista_nombres["A"]

# Primer elemento de la lista, simplificando la salida
mi_lista_nombres[["A"]]

# Primer elemento de la lista, simplificando la salida
mi_lista_nombres$A

# Primer componente del primer elemento de la lista
mi_lista_nombres$A[1]
unlist(mi_lista_nombres[1])[1]

# Primera columna del tercer elemento
mi_lista_nombres$C[, 1]
mi_lista_nombres$`C`[, 1] # Equivalente

# Segundo elemento de la primera columna
# del tercer elemento de la lista
mi_lista_nombres$C[, 1][2]
mi_lista_nombres$C[2, 1] # Equivalente

Si utilizas corchetes dobles en lugar de corchetes simples para obtener subconjuntos de una lista, la clase de la salida se simplificará tanto como sea posible.

Número de elementos de una lista en R

La longitud de una lista es el número de objetos dentro de la lista. Puedes obtener el número de elementos de la lista con la función length. Si quieres conocer la longitud de cualquier objeto dentro de la lista, primero deberás extraer el elemento correspondiente.

# Número de elementos de la lista
length(mi_lista) # 3

# Número de elementos del primer objeto
length(mi_lista[[2]]) # 5

Crear una lista vacía en R

A veces puede ser necesario llenar una lista dentro de un bucle for. Para ese propósito, es interesante crear una lista vacía en R. Aunque puedes crear una lista vacía con la función list, si necesitas una longitud previamente especificada necesitas usar la función vector y especificar la longitud final en el argumento length para crear una lista de tamaño n.

# Lista vacía
lista_vacia <- list()

# Creando una lista vacía con 3 elementos
lista_vacia <- vector("list", length = 3)

Si quisieses llenar la lista dentro de un bucle podrías hacer algo como lo siguiente:

for (j in 1:3) {
    lista_vacia[[j]] <- c(1, 2, 3 * j)
}
[[1]]
[1] 1 2 3

[[2]]
[1] 1 2 6

[[3]]
[1] 1 2 9

Añadir elementos a una lista en R

Si necesitas agregar un elemento a una lista, puedes especificar el objeto que deseas agregar en el siguiente índice a longitud de la lista. Es decir, si la longitud de la lista es 3, puede agregar el nuevo objeto en el cuarto índice.

mi_lista[[4]] <- data.frame(X = c(8, 5, 3), Y = c(7, 9, 1))

# Equivalente, para el caso general de n elementos
mi_lista[[length(mi_lista) + 1]] <- data.frame(X = c(8, 5, 3), Y = c(7, 9, 1)) 

Ahora, imprime tu nueva lista y tendrás el siguiente resultado:

[[1]]
[1] 45 12 56 14

[[2]]
[1] "Coche"  "Bicicleta"

[[3]]
      [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12

[[4]]
   X  Y
1  8  7
2  5  9
3  3  1

Borrar elementos de una lista

Para eliminar algunos elementos de una lista puedes asignar el índice del elemento de la lista que quieres eliminar como NULL o indicar entre corchetes el índice con el operador -. Si deseas eliminar varios elementos a la vez, puedes combinarlos con la función c.

mi_lista[[2]] <- NULL
mi_lista[-2] # Equivalente

# Eliminando el primer y segundo elemento a la vez
mi_lista[-c(1, 2)] 

Lista de listas en R. Listas anidadas

También puedes anidar listas en R. Esto significa que en todos o algunos elementos de tu lista raíz tendrás una lista. Esa lista también puede almacenar otras listas u otros tipos de objetos. Puedes lograr esto con la función list, agregando listas en los elementos. En este ejemplo, vamos añadir a una lista las dos listas creadas en las secciones anteriores.

list_de_listas <- list(mi_lista, mi_lista_nombres)
list_de_listas

Al imprimir la lista anidada obtendrás lo siguiente:

[[1]]
[[1]][[1]]
[1] 45 12 56 14 16

[[1]][[2]]
[1] "Coche"  "Bicicleta"

[[1]][[3]]
      [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12


[[2]]
[[2]]$`A`
[1] 45 12 56 14 16

[[2]]$B
[1] "Coche"  "Bicicleta"

[[2]]$C
      [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12

Accediendo a los elementos de la lista anidada

Acceder a elementos de listas dentro de listas es similar a acceder a los elementos a una única lista. De hecho, si accedes a una lista y la almacenas dentro de un objeto, el proceso es el mismo que se presenta en la sección de extracción de elementos de una única lista. De lo contrario, deberás conocer y seguir el nivel de jerarquía de la lista. Tienes algunos ejemplos en el siguiente bloque de código:

# Accediendo a la primera lista
list_de_listas[[1]]

# Accediendo a la segunda lista
list_de_listas[[2]]

# Primer objeto de la segunda lista
list_de_listas[[2]][[1]] # 45 12 56 14 16

# Tercer elemento del primer objeto
# de la segunda lista
list_de_listas[[2]][[1]][3] # 56
list_de_listas[[2]]$A[3]    # Equivalente

# Puedes guardar las listas en objetos
# y acceder a los elementos de esa lista
# como explicamos en la sección correspondiente
lista_1 <- list_de_listas[[1]]

# Este sería el primer objeto
# de la primera lista
lista_1[[1]] 

Unir listas en R

Puedes juntar o unir dos o más listas listas en R. Para ello, puede usar las funciones append, c o do.call. Al combinar las listas de esta manera, los elementos de la segunda lista se agregarán al final de la primera lista.

# Datos originales
mi_lista <- list(x, y, z)
mi_lista_nombres <- list(A = x, B = y, C = z)

# Concatenar listas
append(mi_lista, mi_lista_nombres)
c(mi_lista, mi_lista_nombres) # Equivalente
do.call(c, list(mi_lista, mi_lista_nombres)) # Equivalente
[[1]]
[1] 45 12 56 14 16

[[2]]
[1] "Coche"  "Bicicleta"

[[3]]
       [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12

$A
[1] 45 12 56 14 16

$B
[1] "Coche"  "Bicicleta"

$C
       [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12

Juntar listas con los mismos nombres

Cuando tienes dos o más listas con los mismos nombres de los elementos, puedes fusionar los elementos de la lista con una lista de la misma longitud que las anteriores, donde se concatenarán los elementos con el mismo nombre. Primero, vamos a copiar nuestra lista con nombres en una nueva variable:

# Copiamos la lista con nombres en un nuevo objeto
mi_lista_nombres_2 <- mi_lista_nombres

Ahora puedes usar las funciones Map o mapply con esas listas de la siguiente manera:

Map(c, mi_lista_nombres, mi_lista_nombres_2)
mapply(c, mi_lista_nombres, mi_lista_nombres_2, SIMPLIFY = FALSE) # Equivalente

Puedes ver el resultado de la lista con elementos concatenados:

$`A`
[1] 45 12 56 14 16 45 12 56 14 16

$B
[1] "Coche"  "Bicicleta" "Coche"  "Bicicleta"

$C
[1]  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9 10 11 12

Nótese que el elemento ‘C’ ya no es una matriz.

Comparar dos listas en R

Puedes comparar dos listas de diferentes maneras: obteniendo los elementos comunes, los diferentes o comparando los que son iguales. En primer lugar, vamos a copiar nuestra primera lista y cambiar el primer elemento.

mi_lista_2 <- mi_lista
mi_lista_2[[1]] <- c(4, 1, 9)

Elementos comunes en dos listas de R

Primero, si quieres obtener cuáles son los elementos iguales entre dos listas, puedes usar la función intersect, que devolverá una lista con los elementos comunes de las listas.

# Devuelve los elementos comunes
intersect(mi_lista, mi_lista_2)
[[1]]
[1] "Coche"  "Bicicleta"

[[2]]
       [, 1] [, 2] [, 3] [, 4]
[1, ]    1     4     7    10
[2, ]    2     5     8    11
[3, ]    3     6     9    12

Elementos diferentes en dos listas de R

En segundo lugar, con la función setdiff obtendrás los elementos diferentes entre las listas. Ten en cuenta que el orden en que pasa las listas es importante.

# ¿Qué está en 'mi_lista' que no está en 'mi_lista_2'?
setdiff(mi_lista, mi_lista_2) # 45 12 56 14 16

# ¿Qué está en 'mi_lista_2' que no está en 'mi_lista'?
setdiff(mi_lista_2, mi_lista) # 4 1 9

Comparar elementos iguales en dos listas de R

En tercer lugar, también puedes comparar los elementos iguales de dos listas con el operador %in% o con la función compare.list de la biblioteca useful. El resultado será un vector lógico.

mi_lista %in% mi_lista_2 # FALSE TRUE TRUE

library(useful)
compare.list(mi_lista, mi_lista_2) # Equivalente

Convertir lista en vector

En ocasiones se necesita convertir una lista a otros tipos de objetos. La conversión más común es convertir una lista en vector. Para ello puedes utilizar la función unlist.

# Primer elemento de la lista a vector
unlist(mi_lista[[1]], use.names = FALSE)
45 12 56 14 16

Si prefieres convertir la lista completa a vector, establece el argumento use.names como FALSE.

# Lista completa como vector
unlist(mi_lista, use.names = FALSE)
"45"   "12"   "56"   "14"   "16"   "Coche"  "Bicicleta" "1"    "2"    "3"   
"4"    "5"    "6"    "7"    "8"    "9"    "10"   "11"   "12"  

Ten en cuenta que en este caso todos los elementos son ahora caracteres.

Además, la biblioteca purrr tiene algunas funciones similares a la función unlist pero en este caso puedes especificar la clase de la salida. En este ejemplo, estamos convirtiendo nuestra nueva lista a tipo ‘double’ y luego a caracter.

mi_lista_3 <- list(c(1, 4), 2, 3)

library(purrr)
flatten_dbl(mi_lista_3) # 1 4 2 3
flatten_chr(mi_lista_3) # "1.000000" "4.000000" "2.000000" "3.000000"

Convertir lista en data frame en R

Supón que tienes una lista que contiene datos de algunas variables. En ese caso, es posible que desees convertir tu lista a un data frame. Para lograrlo, puedes usar las funciones unlist, matrix y data.frame o do.call de la siguiente manera.

mi_lista_4 <- list(c(1, 7, 3), c(9, 8, 1))

data.frame(matrix(unlist(mi_lista_4), nrow = length(mi_lista_4), byrow = TRUE))
do.call(rbind.data.frame, mi_lista_4) # Similar
   X1  X2  X3
1   1   7   3
2   9   8   1

Si estás trabajando con caracteres, establece stringsAsFactors = FALSE para evitar que las columnas de caracteres se conviertan en factor.