我目前有一个包含大约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"
。有没有办法在不诉诸创建新列表的情况下执行此操作,然后循环和重构?
答案 0 :(得分:4)
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
仍然有点不满意,因为这些方法都没有修改列表。
答案 1 :(得分:3)
您可以使用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)))
<强>更新强>
根据Ryan的评论,如果您确实想要更改列表名称本身而不是值,则可以使用此代码:
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
...
答案 2 :(得分:2)
我们可以使用plyr::rename
out <- lapply(List.5000, plyr::rename, c("B" = "Z"))