Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to rename elements inside a list of lists in the an efficient manner in R?

Tags:

r

I currently have a large list with around 5000 elements. A reproducible example is like:

List.5000 <- replicate(5000, c(list(A='A',value.A=10),list(B='B',value.B=20)), simplify = F)

which has:

> List.5000
[[1]]
[[1]]$A
[1] "A"

[[1]]$value.A
[1] 10

[[1]]$B
[1] "B"

[[1]]$value.B
[1] 20


[[2]]
[[2]]$A
[1] "A"

[[2]]$value.A
[1] 10

[[2]]$B
[1] "B"

[[2]]$value.B
[1] 20
....

When I call names(List.5000) it returns NULL. But when I call names(List.5000[[1]]), it gives:

"A"       "value.A" "B"       "value.B"

I would like to change the name "B" to "Z". Is there a way to do this without resorting to creating a new list, then looping and reconstructing?

like image 439
user321627 Avatar asked Jun 03 '18 04:06

user321627


1 Answers

for(i in seq_along(List.5000))
  names(List.5000[[i]])[names(List.5000[[i]]) == 'B'] <-  'Z'

Or, if you prefer lapply/map:

List.5000 <- lapply(List.5000, 
                    function(x) {names(x)[names(x) == 'B'] <-  'Z'; x})

library(purrr)
List.5000 <- map(List.5000, ~{names(.)[names(.) == 'B'] <-  'Z'; .})

If the names really are all the same you could just do

ind <- names(List.5000[[1]]) == 'B'
for(i in seq_along(List.5000))
  names(List.5000[[i]])[ind] <-  'Z'

The bracket syntax is a little faster:

x <- List.5000[[1]]
microbenchmark(
  sub = names(x) <- sub("^B$", "Z", names(x))
  , ifelse = names(x) <- ifelse(names(x) == 'B', 'Z', names(x))
  , stringi = names(x) <- str_replace(names(x), "^B$", "Z")
  , replace = names(x) <- replace(names(x), names(x) == 'B', 'Z')
  , bracket = names(x)[names(x) == 'B'] <-  'Z'
)
# Unit: microseconds
# expr        min       lq      mean   median       uq     max neval
# sub      22.041  31.2265  58.24097  46.9650  78.5075 373.637   100
# ifelse   13.309  22.4110  44.00665  30.2235  65.1395 113.693   100
# stringi 153.880 313.0400 346.41543 358.4795 383.4130 631.354   100
# replace   4.067   6.3205  13.09022   8.1760  11.9280  54.075   100
# bracket   3.246   4.5265  10.38177   5.9180   7.9925  55.278   100

Still a little unsatisfying, as none of these methods modify the list in place.

like image 164
IceCreamToucan Avatar answered Sep 30 '22 23:09

IceCreamToucan