2013-01-14 15 views
6

Podaję listę nie zagnieżdżoną (całkiem prosto). Niektóre elementy to NA, ale można je zastąpić innymi elementami z tej samej listy. Mogę to osiągnąć dzięki globalnemu operatorowi przypisania <<-. Jednak staram się nauczyć lepszej praktyki (ponieważ wydaje mi się, że przy kompilowaniu pakietu dla CRAN mam do czynienia z notes). Pytania:zamień elementy listy (unikaj globalnego przypisania)

  1. Czy mogę to osiągnąć bez zlecenia globalnego?
  2. Jeśli nie, w jaki sposób mogę użyć assign we właściwy sposób (moje podejście wydaje się tworzyć kilka kopii tego samego zestawu danych i może powodować problemy z pamięcią).

Próbowałem przypisać i nie działa. Próbowałem również użyć lapply bez przypisania globalnego, ale mogę uzyskać tylko ostatni zwracany element, a nie listę z każdym zamienionym elementem.

Oto problem:

#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) 
}) 

Docelowo chciałbym to zrobić bez globalnego przydziału, ale jeśli nie to, co jest najlepsze praktyki dla dla CRAN budowania pakietu.

+1

Dlaczego nie uczynić tha t wyświetlić wektor? – Roland

+1

'lapply' +' << - 'zwykle oznacza, że ​​powinieneś używać pętli for. – hadley

+0

@hadley, przydatne informacje. Założę się, że to może pozbyć się niektórych notatek, które dostaję na mojej kompilacji. –

Odpowiedz

10

Jest replace funkcja, która zrobi to za ciebie:

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

Można również użyć nieco prostsze which(is.na(L1)) zamiast match(nulls, names(L1))

4

Dla kompletności oto propozycja Hadley z pętli for jak niektórzy podobny okoliczności nie pozwalają na stosowanie replace:

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