Cómo seleccionar elementos en listas en R

Para seleccionar elementos en una lista de R se utilizan principalmente los operadores [], [[]] y $. La elección depende de si se quiere conservar una lista, extraer directamente un componente o acceder a un elemento mediante su nombre.

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.

Qué es una lista en R

La diferencia es que los elementos de un vector tienen que ser del mismo tipo, mientras que los de una lista pueden ser de distinto tipo. Esta diferencia hace que realmente sean dos tipos de datos con distintas aplicaciones.

Las listas son muy flexibles, pues permiten almacenar cualquier cosa. Los vectores son más específicos, lo que los hace más eficientes y permite que ciertas operaciones, como la suma o la aplicación de operaciones relacionales, tengan sentido.

Las listas se usan principalmente en R para almacenar dos tipos de datos. En primer lugar, colecciones de elementos de un mismo tipo, pero de un tipo tal que no es posible almacenarlo en un vector. En segundo lugar, un conjunto de información heterogénea (de distinto tipo) en un único objeto.

Un ejemplo de este segundo uso son los datos de una persona, que incluyen su nombre (cadena de caracteres), edad (entero), altura en metros (real), etcétera.

Crear una lista en R

Para crear una lista se usa la función list, especificando los elementos o componentes de la lista como argumentos de la función:

Ejemplo básico:

l <- list("Juan", 23, FALSE, c(8, 6.5, 9))

Como ilustra el ejemplo, los componentes pueden ser de distinto tipo.

También puedes crear una lista de elementos con nombre en R. Esto permite acceder fácilmente a elementos específicos de tu lista R.

person <- list(name = "Max White", age = 27, hobbies = c("Programming, movies"))

Para algunas listas resulta más legible hacer que los distintos componentes tengan un nombre. Esto se puede realizar directamente al crear la lista o, a posteriori, con la función names:

names(l) <- c("Nombre", "Edad", "Casado", "Notas")

punto2d <- list(x = 5, y = 6)

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 $.

Los tres operadores para seleccionar elementos

Existen varias formas de indexar una lista, así que usaremos la que nos guste más, nos parezca más legible o sea apropiada al cálculo que queramos realizar. Los operadores para indexar una lista son tres: [], [[]] y $.

Seleccionar con corchetes simples []

La indexación de listas con [] admite las mismas posibilidades que con vectores.

l[c(1, 4)]

l[-c(1, 4)]

l[c("Nombre", "Edad")]

l[c(TRUE, FALSE, FALSE, TRUE)]

Al indexar con [] se obtiene una lista con los componentes seleccionados.

Los corchetes simples son apropiados cuando se desea seleccionar varios componentes o conservar el resultado como una lista, incluso cuando solo se selecciona un componente.

punto2d["x"]

typeof(punto2d["x"])

[1] "list"

Es importante observar que al indexar con [] se obtiene una lista, aunque sólo accedamos a un componente de la lista.

Seleccionar con corchetes dobles [[]]

Cuando queramos acceder al contenido de un único componente de una lista para trabajar con él hay que usar el operador [[]] o el operador $:

punto2d[["x"]]

typeof(punto2d[["x"]])

[1] "double"

punto2d[["x"]] + 2

[1] 7

No es posible realizar la suma con [], porque no se puede aplicar el operador + a una lista.

Cuando usemos el operador [[]] habrá que utilizar un único índice:

l[[4]]

l[["Notas"]]

l[["Notas"]][1]

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.

Los corchetes dobles extraen el contenido del componente, no una lista que contenga ese componente. Por ello son la opción habitual cuando se necesita operar con el valor extraído.

Seleccionar con el operador $

Cuando una lista l tiene nombres asociados a sus componentes, las expresiones l[["Nombre"]] y l$Nombre son equivalentes:

l[["Notas"]]

l$Notas

El operador $ es muy cómodo para acceder al contenido de un componente por su nombre.

También puedes acceder a los elementos por su nombre utilizando corchetes dobles en combinación con el nombre del elemento como una cadena R o el signo del dólar seguido del nombre del elemento:

print(person[["name"]])

print(person$name)

En ambos casos, la instrucción de impresión muestra “Max White” en la pantalla.

Cuando tengamos un componente de una lista con un nombre muy largo, es posible especificarlo con el operador $ escribiendo únicamente los tres primeros caracteres del nombre, salvo que haya ambigüedad porque más de un nombre de componente empiece por esos tres caracteres:

l$Not

El resultado equivale a l$Notas.

Indexación por posición

Para acceder a los elementos de la lista, necesitas el operador R en el que insertas el índice o el nombre.

list <- list(1, TRUE, "Hello world!", c(1,2,3,4))

print(list[[2]])

Este código devuelve “TRUE” o el segundo elemento de la lista.

Ten en cuenta que la indexación en R empieza en uno, no en cero.

La indexación numérica permite seleccionar un componente concreto:

mi_lista[[1]]

También permite seleccionar un elemento dentro de un componente:

mi_lista[[1]][1]

La selección puede continuar por niveles sucesivos cuando el componente contiene un vector, una matriz o cualquier otra estructura indexable.

Seleccionar varios componentes

Para seleccionar varios componentes se utiliza un vector de índices positivos:

l[c(1, 4)]

El resultado contiene el primer y el cuarto componente de la lista.

Una solución general para seleccionar el primer y el último componente es:

l[c(1, length(l))]

La indexación con un vector de números negativos excluye los componentes indicados:

l[-c(1, 4)]

Para eliminar el primer y segundo elemento a la vez también puede utilizarse:

mi_lista[-c(1, 2)]

La selección mediante un vector de cadenas permite extraer varios componentes con nombre:

l[c("Nombre", "Edad")]

También es posible seleccionar componentes mediante un vector lógico:

l[c(TRUE, FALSE, FALSE, TRUE)]

Seleccionar elementos dentro de componentes

La selección de un componente y la selección de un elemento dentro de ese componente son operaciones distintas.

mi_lista[[1]]

El primer ejemplo extrae el primer componente de la lista.

mi_lista[[1]][1]

El segundo ejemplo extrae el primer elemento del primer componente de la lista.

En una matriz incluida dentro de una lista pueden seleccionarse filas y columnas con la sintaxis habitual:

mi_lista[[3]][, 1]

Esta expresión selecciona la primera columna del tercer elemento de la lista.

mi_lista[[3]][2, 1]

Esta expresión selecciona el elemento situado en la segunda fila y la primera columna del tercer componente.

También puede escribirse:

mi_lista[[3]][, 1][2]

El resultado es equivalente.

Listas anidadas

Los componentes de una lista pueden ser de cualquier tipo, incluido el propio tipo lista. Un tipo de dato, como las listas, que admite elementos de su propio tipo se dice que es recursivo.

También puedes anidar listas en R. Esto significa que en todos o algunos elementos de tu lista raíz tendrás una lista.

fecha <- list(dia = 4, mes = "febrero", año = 2002)

alumno <- list(nombre = "Marta", nacimiento = fecha)

En este caso el componente nacimiento de la lista alumno es una lista.

Para acceder a un componente de una lista anidada se siguen los niveles de jerarquía:

alumno$nacimiento$año

alumno[["nacimiento"]][["año"]]

Las dos expresiones permiten acceder al valor del año.

También puedes anidar listas utilizando la función list:

list_de_listas <- list(mi_lista, mi_lista_nombres)

Acceder a elementos de listas dentro de listas es similar a acceder a los elementos a una única lista.

list_de_listas[[1]]

list_de_listas[[2]]

list_de_listas[[2]][[1]]

list_de_listas[[2]][[1]][3]

list_de_listas[[2]]$A[3]

En este último caso, list_de_listas[[2]]$A[3] es equivalente a list_de_listas[[2]][[1]][3].

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.

lista_1 <- list_de_listas[[1]]

lista_1[[1]]

Seleccionar componentes por una condición

La selección lógica permite conservar los componentes que cumplen una condición calculada previamente.

l <- list(1:5, 3:11, 3:1, 2:9)

longitud <- sapply(l, length)

l[longitud >= 5]

La función sapply calcula la longitud de cada componente y el indexado lógico conserva aquellos cuya longitud es mayor o igual a 5.

Funciones útiles para trabajar con listas

length()

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:

length(l)

length(punto2d)

Si quieres conocer la longitud de cualquier objeto dentro de la lista, primero deberás extraer el elemento correspondiente.

length(mi_lista[[2]])

La expresión length(mi_lista[[2]]) calcula la longitud del segundo objeto de la lista, mientras que length(mi_lista) calcula el número de componentes de la lista.

names()

Si has creado una lista R con nombres, utiliza la función de lista R names() para mostrar los nombres de los objetos de tu lista.

identifier <- names(person)

La función asume una lista como parámetro de transferencia.

str()

Dado que una lista puede contener componentes de distintos tipos, incluso de tipo lista, no resulta fácil visualizarla en la consola.

La función str produce una visualización algo más estructurada en la consola:

str(l)

La función str es genérica, por lo que puede aplicarse a cualquier objeto, no sólo a listas.

lapply() y sapply()

La función lapply permite aplicar una función a los distintos componentes de una lista.

La salida de lapply es una lista. Por cada componente de la lista de entrada se genera un componente en la lista de salida con el resultado de aplicar la función al componente de la lista de entrada:

lapply(l, length)

Si, como en este caso, la aplicación de la función produce elementos del mismo tipo, se puede usar la función sapply para obtener la salida en un vector:

sapply(l, length)

La función lapply también se puede aplicar a vectores:

v <- c(25, 4, 60)

lapply(v, sqrt)

sapply(v, sqrt)

Para este ejemplo, sin embargo, sería más sencillo usar:

sqrt(v)

Para seleccionar componentes por su longitud puede utilizarse:

longitud <- sapply(l, length)

l[longitud >= 5]

append()

append() te permite añadir elementos al final de tu lista.

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

append(list, 5)

La función asume la lista a la que se va a añadir el elemento como primer parámetro de paso y el elemento que se va a insertar como segundo parámetro.

La función de lista append() en R no es la única forma de añadir elementos a tu lista.

c()

En R, puedes combinar dos listas en una.

Para ello, puedes utilizar la función c(), que asume ambas listas como parámetro y devuelve una lista concatenada.

list1 <- list(1,2,3,4)

list2 <- list(5,6,7,8)

list_concatenate <- c(list1, list2)

Crear, modificar y eliminar componentes

Crear una lista vacía

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:

lista_vacia <- list()

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_vacia <- vector("list", length = 3)

Añadir componentes

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))

El equivalente para el caso general de n elementos es:

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

A menudo, la anotación de índice con corchetes dobles, en la que utilizas un índice que aún no existe, funciona más rápidamente:

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

list[[5]] <- 5

También puede añadirse un componente con nombre utilizando el operador $:

punto2d$z <- 10

Modificar componentes

Los componentes existentes pueden modificarse mediante su posición o su nombre:

l <- list(a = 1, b = 2, c = "x", d = "y")

l[[3]] <- TRUE

También vale:

l$c <- TRUE

Eliminar componentes

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 -.

mi_lista[[2]] <- NULL

mi_lista[-2]

Los dos procedimientos permiten eliminar el segundo componente, aunque el segundo conserva una lista con los componentes restantes.

Para eliminar un componente con nombre se puede utilizar:

punto2d$z <- NULL

Seleccionar elementos de listas devueltas por funciones

Muchas funciones de R devuelven información diversa sobre los cálculos que realizan.

Como en R una función sólo puede devolver un objeto, la forma usual de devolver esta información es en una lista con distintos componentes, cada componente almacena algún tipo de dato sobre el cómputo realizado por la función.

La función hist calcula un histograma sobre una muestra y lo visualiza en la pantalla, pero también devuelve una lista con información sobre sus características:

salida <- hist(rnorm(1000, 5, 3))

typeof(salida)

str(salida)

Los distintos componentes de la lista salida nos aportan información sobre el histograma construido.

Por ejemplo, los componentes pueden seleccionarse mediante:

salida$breaks

salida$counts

salida$density

Convertir listas en otras estructuras

Aunque las listas R son una estructura de datos versátil, puede que necesites otras estructuras de datos, como vectores o dataframes, para determinados fines.

Si este es el caso, simplemente convierte tu lista.

Convertir una 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:

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

vector <- unlist(list)

Si quieres convertir tu lista en un vector R, utiliza la función unlist(), que toma una lista en R como parámetro de transferencia y la convierte en un vector.

La lista que pases a la función también puede ser multidimensional.

Si una lista que contiene datos de distintos tipos de datos la conviertes en un vector, puede producirse un comportamiento imprevisto, porque los vectores en R solo pueden almacenar datos del mismo tipo de datos por defecto.

Por eso solo se recomienda llamar a unlist() si los elementos de tu lista son del mismo tipo de datos.

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

unlist(mi_lista, use.names = FALSE)

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

Convertir una lista en data.frame

Los dataframes en R se utilizan, entre otras cosas, para la representación tabular de conjuntos de datos.

Por eso las listas multidimensionales pueden convertirse fácilmente en dataframes en R.

No obstante, debes tener en cuenta que las listas deben tener el mismo número de elementos.

Para convertir una lista en R en un dataframe, R proporciona la función data.frame(), que espera la lista a convertir como parámetro de paso.

people <- list(name=c("Max", "Mia", "Mika"), age=c(27, 32, 23))

table <- data.frame(people)

print(table)

El dataframe creado por el código anterior tiene el siguiente aspecto:

nameage
Max27
Mia32
Mika23

Para convertir una lista de vectores en un data frame también pueden utilizarse las funciones unlist, matrix y data.frame o do.call:

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)

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

Seleccionar elementos de un data.frame

El acceso a los datos que se encuentran en un data.frame es muy similar al acceso a los datos de una matriz que ya vimos en la sección anterior.

Sin embargo, para los data.frames R dispone de algunas funciones que facilitan la tarea de seleccionar o filtrar datos.

Los dataframes son una clase de objetos especial en R.

Normalmente, cuando se realiza un estudio estadístico sobre los sujetos u objetos de una muestra, la información se organiza precisamente en un dataframe: una hoja de datos, en los que cada fila corresponde a un sujeto y cada columna a una variable.

La diferencia es que una matriz sólo admite valores numéricos, mientras que en un dataframe podemos incluir también datos alfanuméricos.

Seleccionar filas y columnas con []

Si queremos ver sólo los datos de los sujetos (filas) 3 a 6, escribiríamos:

misDatos[3:6,]

Si queremos seleccionar los datos de edad, que corresponde a la primera columna, podemos tratar a misDatos igual que si fuese una matriz:

misDatos[,1]

La primera posición selecciona las filas y la segunda las columnas.

Por tanto, misDatos[3:6,] selecciona las filas 3 a 6 y todas las columnas, mientras que misDatos[,1] selecciona todas las filas de la primera columna.

Seleccionar una columna por nombre

También podemos referirnos a la columna por su nombre:

misDatos$edad

En este caso hemos de utilizar el nombre del data.frame, seguido del símbolo $ y del nombre de la variable que nos interesa.

De manera equivalente, la selección de esa variable puede realizarse mediante:

misDatos[,"edad"]

o poniendo el nombre de la variable entre dobles corchetes y entre comillas:

misDatos[["edad"]]

Así pues, los siguientes comandos son equivalentes y dan el mismo resultado:

mean(misDatos[,1])

mean(misDatos$edad)

mean(misDatos[,"edad"])

mean(misDatos[["edad"]])

Filtrar con subset()

La función subset() nos permite seleccionar una parte del data.frame.

Por ejemplo, si deseamos crear dos dataframes nuevos, uno solo con los hombres y otro con las mujeres utilizaríamos:

hombres=subset(misDatos,sexo=="H")

mujeres=subset(misDatos,sexo=="M")

La función subset() permite expresar la condición utilizando directamente los nombres de las columnas del data.frame.

Podemos elaborar selecciones más complejas.

Para seleccionar sujetos que sean hombres y tengan más de 30 años, la condición “y” se especifica mediante el símbolo “&”:

mayores=subset(misDatos,sexo=="H" & edad>30)

Para seleccionar hombres que tengan menos de 30 años y hayan hablado por el móvil más de 12 minutos diarios:

jov_habladores=subset(misDatos,sexo=="H" & edad<30 & tiempo>12)

La condición “o” se expresa mediante la línea vertical “|”:

extremos=subset(misDatos,edad<25|edad>30)

También podemos seleccionar un subconjunto de variables del data.frame.

Por ejemplo, si nos interesan solo la edad y el tiempo de uso del móvil de los hombres de la muestra:

hombres=subset(misDatos,sexo=="H", select=c(edad, tiempo))

Comparar y unir listas

Concatenar listas

Puedes juntar o unir dos o más 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.

append(mi_lista, mi_lista_nombres)

c(mi_lista, mi_lista_nombres)

do.call(c, list(mi_lista, mi_lista_nombres))

Unir 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.

Map(c, mi_lista_nombres, mi_lista_nombres_2)

mapply(c, mi_lista_nombres, mi_lista_nombres_2, SIMPLIFY = FALSE)

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

Comparar listas

Puedes comparar dos listas de diferentes maneras: obteniendo los elementos comunes, los diferentes o comparando los que son iguales.

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.

intersect(mi_lista, mi_lista_2)

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.

setdiff(mi_lista, mi_lista_2)

setdiff(mi_lista_2, mi_lista)

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

library(useful)

compare.list(mi_lista, mi_lista_2)

Ideas clave para elegir el operador

  • []: devuelve una lista con los componentes seleccionados.
  • [[]]: extrae directamente el contenido de un único componente.
  • $: permite acceder de forma cómoda al contenido de un componente con nombre.
  • Indexación numérica: resulta útil cuando se conoce la posición del componente.
  • Indexación por nombre: mejora la legibilidad cuando los componentes tienen nombres.
  • Indexación lógica: permite conservar los componentes que cumplen una condición.
  • subset(): facilita el filtrado de filas y columnas de un data.frame.
noimgs

tags: #como #seleccionar #en #listas #r