2017-02-27 52 views
1

我有所有相同结构的列表的列表,我想更改第二层中每个列表的一个元素。换句话说,我有一个包含对象x,y & z的列表。该列表在另一个列表中重复多次。我需要在每个列表中更改x。做这个的最好方式是什么?使用lapply更改列表的列表

我目前的做法是创建一个小功能,执行我想要的更改,然后重新创建列表。但是有什么让我觉得有更简单的方法来做到这一点?

下面的代码显示了我的方法,这对我的玩具例子来说很好 - 但是对象更加复杂的真实上下文,所以我不想多次重新创建它,因为我只更改一个值。我可以这样做,它只是感觉错综复杂。

l = list(x = 1:3, y = "a", z = 9) 
test = list(l, l, l) 

standardize = function(obj){ 
    obj$x = obj$x/max(obj$x) 
    list(obj$x, obj$y, obj$z) 
} 

lapply(test, function(e) standardize(e)) 

回答

3

只需返回修改的obj而不是重新创建列表。

standardize = function(obj){ 
    obj$x <- obj$x/max(obj$x) 
    obj 
} 

奖励:obj元素的名称现在保留。

+0

非常感谢!现在感觉有点傻! – SamPassmore

1

随着purrr:

library(purrr) 

test2 <- test %>% map(map_at, 'x', ~.x/max(.x)) 

test2 <- test %>% map(update_list, x = ~x/max(x)) 

无论哪种方式,你会得到

str(test2) 
## List of 3 
## $ :List of 3 
## ..$ x: num [1:3] 0.333 0.667 1 
## ..$ y: chr "a" 
## ..$ z: num 9 
## $ :List of 3 
## ..$ x: num [1:3] 0.333 0.667 1 
## ..$ y: chr "a" 
## ..$ z: num 9 
## $ :List of 3 
## ..$ x: num [1:3] 0.333 0.667 1 
## ..$ y: chr "a" 
## ..$ z: num 9 
0

鉴于你的列表的大小已经是固定的,这是一种情况,一个简单的for循环也很适合这个任务。

for(i in seq_along(test)){ 
    test[[i]]$x <- test[[i]]$x/max(test[[i]]$x) 
} 

我时钟此为比lapply溶液慢仅仅0.8毫秒。