Как переименовать элементы в списке списков эффективным способом в R? - PullRequest
0 голосов
/ 03 июня 2018

У меня в настоящее время большой список с около 5000 элементов.Воспроизводимый пример имеет вид:

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

, который имеет:

> 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
....

Когда я звоню names(List.5000), возвращается NULL.Но когда я звоню names(List.5000[[1]]), это дает:

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

Я хотел бы изменить имя "B" на "Z".Есть ли способ сделать это, не прибегая к созданию нового списка, а затем к циклу и восстановлению?

Ответы [ 3 ]

0 голосов
/ 03 июня 2018
for(i in seq_along(List.5000))
  names(List.5000[[i]])[names(List.5000[[i]]) == 'B'] <-  'Z'

Или, если вы предпочитаете 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'; .})

Если имена действительно одинаковы, вы можете просто сделать

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

Синтаксис скобок немного быстрее:

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

Все еще немного неудовлетворительно, поскольку ни один из этих методов не изменяет список на месте.

0 голосов
/ 03 июня 2018

Мы могли бы использовать plyr::rename

out <- lapply(List.5000, plyr::rename, c("B" =  "Z"))
0 голосов
/ 03 июня 2018

Вы можете использовать purrr:map() и sub():

library(purrr)

map(List.5000, ~sub("^B$", "Z", names(.x)))

Или использовать stringr::str_replace, чтобы сохранить синтаксис tidyverse:

library(stringr)

map(List.5000, ~str_replace(names(.x), "^B$", "Z"))

Вы даже недействительно нужно purrr, вы можете просто использовать lapply, но я действительно считаю purrr более понятным синтаксисом:

lapply(List.5000, function(x) sub("^B$", "2", names(x)))

Обновление
Согласно комментарию Райана, есливы на самом деле хотите изменить имена самих списков, но не их значения, вы можете использовать это вместо:

change_names <- function(x) {
  names(x) <- sub("^B$", "Z", names(x))
  x
}
map(List.5000, ~change_names(.x))

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

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

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

[[1]]$value.B
[1] 20
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...