I am applying a function to the elements of a list.
the list has names
, so in a sense each element has its own name, but how do I access it once the lapply
function has already extracted/separated the element from the list?
Some fictive data (as internal function I'm here misusing dput
):
r <- list(a=structure(1:4, unit="test"), b='abc')
lapply(r, dput)
What I observe here is that dput
receives the objects in the list as if accessed with [[
, deprived of the name they have in the containing list.
So I thought I would drop the idea of using functions from the apply
family and write a loop, but I don't particularly like the idea and it obliges me to construct the result of the complete function.
result <- list()
for (name in names(r)) {
print(name)
result[[name]] <- dput(r[[name]])
}
result
Any insightful thoughts?
You can simulate the idea behind loops whilst still using lapply
, by passing a numeric vector to lapply
and then using that as an index to extract the elements from the list you want. That probably makes no sense, but hopefully the example illustrates what I mean:
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"
The key idea is that seq_along(x)
returns a sequence of the same length as x
. For example:
> seq_along(r)
[1] 1 2
See ?seq_along
for more detail.
EDIT
This seems to be very marginally faster than indexing by name:
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
You could use 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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With