2013-01-14 10 views
6

I lave un elenco non annidato (piuttosto semplice). Alcuni elementi sono NA ma possono essere sostituiti con altri elementi dalla stessa lista. Posso raggiungere questo obiettivo con l'operatore di assegnazione globale <<-. Tuttavia sto cercando di imparare le pratiche migliori (dato che sembra darmi notes durante la compilazione di un pacchetto per CRAN). Domande:sostituire gli elementi della lista (evitare l'assegnazione globale)

  1. Posso ottenere questo senza un incarico globale?
  2. In caso contrario, come è possibile utilizzare assign in modo appropriato (il mio approccio sembra fare un sacco di copie dello stesso set di dati e potrebbe incorrere in problemi di memoria).

Ho provato ad assegnare e non funziona. Ho anche provato a utilizzare lapply senza assegnazione globale, ma posso ottenere solo l'ultimo elemento restituito anziché l'elenco con ogni elemento sostituito.

Ecco il problema:

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

In definitiva, mi piacerebbe fare questo senza assegnazione globale, ma, se non che ciò che è migliore pratica per un per CRAN build di un pacchetto.

+1

Perché non si fanno tha t elencare un vettore? – Roland

+1

'lapply' +' << - 'di solito implica che dovresti usare un ciclo for. – hadley

+0

@hadley, informazioni utili. Scommetto che questo potrebbe sbarazzarsi di alcune delle note che sto ottenendo sul mio pacchetto. –

risposta

10

C'è una funzione replace che farà questo per voi:

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

Si potrebbe anche usare il leggermente più semplice which(is.na(L1)), invece di match(nulls, names(L1))

4

Per completezza ecco il suggerimento di Hadley di un ciclo for come alcuni simili le circostanze non consentirebbero di utilizzare replace:

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