2013-01-14 20 views
6

我拥有一个非嵌套列表(非常简单)。一些元素是NAs,但可以用同一列表中的其他元素替换。我可以通过全球分配运营商<<-实现此目的。不过,我试图学习更好的做法(因为这似乎给我编译一个包的CRAN notes)。问题:替换列表元素(避免全局分配)

  1. 我可以在没有全局分配的情况下实现吗?
  2. 如果不是我怎么能适当地使用assign(我的方法似乎使一堆相同的数据集的副本,并可能遇到内存问题)。

我试过分配,它不起作用。我也尝试使用lapply而没有全局分配,但是我只能得到最后返回的元素,而不是每个元素都被替换的列表。

这里的问题:

#Fake Data 
L1 <- lapply(1:3, function(i) rnorm(1)) 
L1[4:5] <- NA 
names(L1) <- letters[1:5] 

#items to replace and their replacements (names of elements to replace) 
nulls <- names(L1[sapply(L1, function(x) is.na(x))]) 
replaces <- c("b", "a") 

#doesn't work (returns only last element) 
lapply(seq_along(nulls), function(i) { 
    L1[[nulls[i]]] <- L1[[replaces[i]]] 
    return(L1) 
}) 

#works but considered bad practice by many 
lapply(seq_along(nulls), function(i) { 
    L1[[nulls[i]]] <<- L1[[replaces[i]]] 
}) 

#does not work (I try L1[["d"]] and still get NA) 
lapply(seq_along(nulls), function(i) { 
    assign(paste0("L1[[", nulls[i], "]]"), L1[[replaces[i]]], envir = .GlobalEnv) 
}) 

#also bad practice bu I tried 
lapply(seq_along(nulls), function(i) { 
    assign(paste0("L1$", nulls[i]), L1[[replaces[i]]], envir = .GlobalEnv) 
}) 

#This works but it feels like we're making a ton of copies of the same data set 
lapply(seq_along(nulls), function(i) { 
    L1[[nulls[i]]] <- L1[[replaces[i]]] 
    assign("L1", L1, envir = .GlobalEnv) 
}) 

最后,我想这样做没有全局分配,但如果没有,什么是对的CRAN构建一个软件包的最佳实践。

+1

你为什么不使用临时列出一个向量? – Roland

+1

'lapply' +'<< - '通常意味着你应该使用for循环。 – hadley

+0

@hadley,有用的信息。我敢打赌,这可以摆脱我在我的包构建中得到的一些笔记。 –

回答

10

有一个replace功能会为你做到这一点:

replace(L1, match(nulls, names(L1)), L1[match(replaces, names(L1))]) 

您也可以使用稍微简单which(is.na(L1)),而不是match(nulls, names(L1))

4

为了完整这里的哈德利的建议for循环一些类似情况下不会允许使用replace

for(i in seq_along(a[!apps])){ 
    L1[[nulls[i]]] <- L1[[replaces[i]]] 
}