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 № 1Puedes 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"