Menu

Listas en R: crear, acceder ([[ frente a $ frente a [) y modificar

Las listas son el contenedor para todo de R: tipos mezclados, estructuras anidadas, data frames enteros. La habilidad clave es saber cuándo [ devuelve una lista más pequeña y cuándo [[ devuelve el elemento en sí.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Una lista guarda cualquier cosa

Un vector tiene una regla estricta: todos los elementos deben ser del mismo tipo. Una lista no tiene esa regla. Cada elemento de una lista puede ser de un tipo distinto, de una longitud distinta, incluso otra lista. Es el contenedor de propósito general de R:

length() informa de 4 - cuatro elementos, aunque uno de ellos (scores) contenga a su vez tres números. Una lista cuenta sus compartimentos, no lo que hay dentro de ellos. str() (structure) es la forma más rápida de ver qué contiene realmente una lista - una línea por elemento con su nombre, tipo y una vista previa. Que str() sea un reflejo: siempre que una función te entregue algo y no estés seguro de qué es, hazle str().

Los nombres son opcionales (list(1, "a", TRUE) es legal) pero casi siempre merecen la pena - una lista con nombres se documenta a sí misma.

Las tres vías de entrada: [, [[ y $

Esta es la parte de las listas que todo el mundo se equivoca una vez, así que hagámosla exactamente bien. Hay tres operadores de acceso y hacen dos trabajos diferentes:

  • [ devuelve una lista más pequeña - un contenedor del mismo tipo, con lo que hayas seleccionado.
  • [[ devuelve el elemento en sí - el valor real dentro del compartimento.
  • $ es la abreviatura de [[ con un nombre literal: person$age es person[["age"]].

La diferencia es invisible cuando imprimes a la ligera y muy visible en cuanto intentas calcular:

person["scores"] tiene clase "list" - una lista de longitud 1 con el vector de puntuaciones dentro. person[["scores"]] tiene clase "numeric" - el vector en sí, listo para mean(). Llama a mean() sobre la versión de corchete simple y obtendrás un error sobre que el argumento no es numérico; ese mensaje de error casi siempre es señal de que usaste [ donde querías decir [[.

Una metáfora que se queda: una lista es un tren. [ te da un tren más corto - sigue siendo un tren. [[ abre un vagón y te entrega la carga.

Entonces, ¿cuándo es [ la herramienta correcta? Cuando quieres varios elementos y quieres mantenerlos empaquetados:

No puedes extraer dos elementos "en sí" a la vez - dos valores necesitan un contenedor -, así que la selección de varios elementos siempre es de corchete simple y siempre produce una lista.

Una diferencia más: $ usa coincidencia parcial (person$sc encuentra scores si no es ambiguo), lo que resulta cómodo en la consola y peligroso en los scripts. En código que debe seguir funcionando, prefiere [[ con el nombre completo - además acepta un nombre guardado en una variable, algo que $ no puede hacer.

Añadir, cambiar, eliminar

Las listas crecen y encogen con asignaciones normales - no hace falta ningún método especial de añadido:

  • Asignar a un nombre que todavía no existe añade el elemento.
  • Asignar a un nombre existente lo reemplaza.
  • Asignar a la posición length(x) + 1 añade un elemento sin nombre al final.
  • Asignar NULL elimina el elemento por completo - la lista se acorta. (Este es el único sitio donde NULL actúa como una orden de borrado; si de verdad necesitas guardar "nada" en un compartimento, usa x["k"] <- list(NULL).)

Para pegar dos listas de principio a fin, c() funciona con listas igual que con vectores: c(list_a, list_b) devuelve una lista más larga.

Listas anidadas

Como un elemento de una lista puede ser otra lista, las listas se anidan a cualquier profundidad - lo que las convierte en la forma natural de R para datos estructurados como JSON parseado o resultados agrupados:

Profundizar no es más que encadenar accesores - cada $ o [[ baja un nivel. Cuando una estructura anidada se vuelve confusa, str(company) muestra todo el árbol de una vez, y str(company, max.level = 1) muestra solo la capa superior.

Aplanar con unlist()

unlist() colapsa una lista - por muy anidada que esté - en un único vector:

Dos cosas que notar. Primera, unlist() construye nombres por ti (math1, math2, art) para que todavía puedas saber de dónde vino cada valor. Segunda - y esta es la trampa -, un vector solo guarda un tipo, así que aplanar una lista mezclada coacciona todo al tipo más flexible presente. El número 1 volvió como la cadena "1". Si aplanas y tus números se convierten en texto, la lista no era tan uniforme como pensabas.

Por qué importan las listas

Las listas pueden parecer un tema de principiante que superarás. Es al revés - son estructurales en todo el lenguaje:

  • Las funciones que devuelven varias cosas devuelven una lista. Las funciones de R devuelven un objeto; una lista hace que ese único objeto lleve un valor ajustado aquí y una tabla de coeficientes allá. Cuando ejecutas una regresión, el objeto de modelo que recibes es una lista (grande y con clase) - un str() sobre él lo demuestra.
  • Un data frame es una lista de columnas - vectores de igual longitud con algún comportamiento extra encima. Todo lo que acabas de aprender ($, [[, asignar NULL para eliminar un elemento) se aplica literalmente a las columnas de un data frame.
  • La familia apply - lapply() y compañía - toma una lista, aplica una función a cada elemento y devuelve una lista. Listas dentro, listas fuera es la forma estándar del cálculo repetido en R.

Lo que te llevas

  • Las listas guardan cualquier cosa: tipos mezclados, longitudes desiguales, otras listas, data frames enteros.
  • [ devuelve una lista más pequeña; [[ devuelve el elemento en sí; $ es [[ con un nombre literal. ¿Vas a hacer cálculos? Quieres [[ o $.
  • Añade asignando a un nombre nuevo, elimina asignando NULL, combina con c().
  • unlist() aplana a un vector y coacciona los tipos mezclados por el camino - comprueba la clase del resultado.
  • Los data frames son listas de columnas, así que este conocimiento se transfiere directamente.

Lo siguiente: las matrices - la contraparte de un solo tipo, con filas y columnas, de la lista.

Preguntas frecuentes

¿Cuál es la diferencia entre [ y [[ en R?

Los corchetes simples [ siempre devuelven una lista con los elementos seleccionados - un contenedor más pequeño del mismo tipo. Los corchetes dobles [[ entran dentro y devuelven el elemento en sí. Si x$scores guarda un vector numérico, x["scores"] es una lista de longitud 1 y x[["scores"]] es el vector numérico. Usa [[ (o $) cuando quieras trabajar de verdad con el valor.

¿Cómo se añade un elemento a una lista en R?

Asigna a un nombre que todavía no exista: x$email <- "rosa@example.com" o x[["email"]] <- .... La lista crece automáticamente. Para añadir al final sin nombre, asigna a la posición siguiente: x[[length(x) + 1]] <- value. Para eliminar un elemento, asígnale NULL: x$email <- NULL.

¿Cómo se convierte una lista en un vector en R?

unlist(x) aplana una lista (incluidas las anidadas) en un único vector. Como un vector solo guarda un tipo, todo se coacciona al tipo más flexible presente - una lista de números y cadenas se convierte en un vector de caracteres. Comprueba la class() del resultado después de aplanar.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR