Suppose I have a list nested within a list and I have some function which only works on vectors (like str_replace from the stringr package). The function should do its work on every element which actually entails information, ...
Question 1: Is there a specific solution to my problem?
Question 2: Is there a general solution?
There should be a solution using loops, but that is all but elegant and probably very slow - efficiency does play a role here.
Let's have an example:
# let's start easy:
test1 <- list(c("a","d"),c("b","d"),c("c","d"))
# does not work:
str_replace(test1,"d","changed")
# but this does:
lapply(test1,str_replace,"d","changed")
# but what now ?
test2 <- list(c(list("a"),"d"),c("b","d"),c("c","d"))
# does not work! :-(
lapply(test2,str_replace,"d","changed")
Here is how to use rapply for this. Note the position of the ... in the definition of rapply - this comes after dflt
and how
. For this reason, we name the arguments to str_replace:
rapply(test,str_replace,pattern="d",replacement="changed",how='replace')
[[1]]
[[1]][[1]]
[1] "a"
[[1]][[2]]
[1] "changed"
[[2]]
[1] "b" "changed"
[[3]]
[1] "c" "changed"
You can use unlist
/relist
:
library(stringr)
test <- list(c(list("a"),"d"),c("b","d"),c("c","d"))
test2 <- unlist(test)
test2 <- str_replace(test2,"d","changed")
relist(test2,test)
[[1]]
[[1]][[1]]
[1] "a"
[[1]][[2]]
[1] "changed"
[[2]]
[1] "b" "changed"
[[3]]
[1] "c" "changed"
I believe this is pretty efficient, but have not tested.
rapply
recursively applies a function to each list element. You might have to experiment with the parameter how
to get the right output, but it should give you what you need.
rapply
documentation is here.
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