/ / ¿Cómo hago un bucle en una lista y accedo a los nombres y atributos? - r

¿Cómo hago un bucle en una lista y accedo a los nombres y atributos? - r

Estoy aplicando una función a los elementos de una lista.

la lista tiene names, así que, en cierto sentido, cada elemento tiene su propio nombre, pero ¿cómo puedo acceder a él una vez que lapply ¿La función ya ha extraído / separado el elemento de la lista?

Algunos datos ficticios (como función interna estoy aquí mal uso dput)

r <- list(a=structure(1:4, unit="test"), b="abc")
lapply(r, dput)

Lo que observo aquí es que dput recibe los objetos en la lista como si se accediera con [[, privados del nombre que tienen en la lista que lo contiene.

Entonces pensé que abandonaría la idea de usar funciones del apply familia y escribir un ciclo, pero no me gusta especialmente la idea y me obliga a construir el resultado de la función completa.

result <- list()
for (name in names(r)) {
print(name)
result[[name]] <- dput(r[[name]])
}
result

¿Alguna idea perspicaz?

Respuestas

5 para la respuesta № 1

Puedes simular la idea detrás de los bucles mientras sigues usando lapply, pasando un vector numérico a lapply y luego usar eso como un índice para extraer los elementos de la lista que desee. Eso probablemente no tiene sentido, pero espero que el ejemplo ilustra lo que quiero decir:

lapply(seq_along(r), function(i)dput(r[i]))

structure(list(a = structure(1:4, unit = "test")), .Names = "a")
structure(list(b = "abc"), .Names = "b")
[[1]]
[[1]]$a
[1] 1 2 3 4
attr(,"unit")
[1] "test"



[[2]]
[[2]]$b
[1] "abc"

La idea clave es que seq_along(x) devuelve una secuencia de la misma longitud que x. Por ejemplo:

> seq_along(r)
[1] 1 2

Ver ?seq_along para más detalles.


EDITAR

Esto parece ser marginalmente más rápido que indexar por nombre:

library(rbenchmark)
benchmark(
xx <- lapply(names(r), function(i)dput(r[i])),
yy <- lapply(seq_along(r), function(i)dput(r[i])),
replications=10000)

test replications elapsed relative user.self
1     xx <- lapply(names(r), function(i) dput(r[i]))        10000    1.95 1.026316      1.70
2 yy <- lapply(seq_along(r), function(i) dput(r[i]))        10000    1.90 1.000000      1.66
sys.self user.child sys.child
1     0.00         NA        NA
2     0.01         NA        NA

2 para la respuesta № 2

Podrías usar mapply:

dummy <- function(value, name) {
list(
name_of_element = name,
value_of_element = value
)
}
str(mapply(dummy, r, names(r), SIMPLIFY=FALSE))
# List of 2
# $ a:List of 2
# ..$ name_of_element : chr "a"
# ..$ value_of_element: atomic [1:4] 1 2 3 4
# .. ..- attr(*, "unit")= chr "test"
# $ b:List of 2
# ..$ name_of_element : chr "b"
# ..$ value_of_element: chr "abc"