2009-03-16 31 views
180

Ho una lista e voglio rimuovere un singolo elemento da esso. Come posso fare questo?Come posso rimuovere un elemento da un elenco?

Ho provato a cercare ciò che penso che i nomi ovvi di questa funzione sarebbero nel manuale di riferimento e non ho trovato nulla di appropriato.

risposta

157

Non so R a tutti, ma un po 'di googling creativo mi ha portato qui: http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

La citazione chiave da lì:

I do not find explicit documentation for R on how to remove elements from lists, but trial and error tells me

myList[[5]] <- NULL

will remove the 5th element and then "close up" the hole caused by deletion of that element. That suffles the index values, So I have to be careful in dropping elements. I must work from the back of the list to the front.

A response to that post later in the thread stati:

For deleting an element of a list, see R FAQ 7.1

E il relevant section of the R FAQ dice:

... Do not set x[i] or x[[i]] to NULL, because this will remove the corresponding component from the list.

Che sembra dirvi (in un modo un po 'indietro) come rimuovere un elemento.

Spero che ti aiuti o almeno ti guidi nella giusta direzione.

+2

Grazie, mylist [i] <- nulla è esattamente il modo di farlo –

+27

Questo non ha funzionato per me.Ottengo: 'Errore nella lista [lunghezza (lista)] <- NULL: la sostituzione ha lunghezza zero' – wbarksdale

+1

@Aleksandr Il post di Levchuck mi ha mostrato che stavo effettivamente trattando un vettore e avevo bisogno di creare un nuovo oggetto – wbarksdale

148

Se non si desidera modificare l'elenco sul posto (ad esempio per passare l'elenco con un elemento rimosso in una funzione), è possibile utilizzare l'indicizzazione: gli indici negativi indicano "non includere questo elemento".

x <- list("a", "b", "c", "d", "e"); # example list 

x[-2];  # without 2nd element 

x[-c(2, 3)]; # without 2nd and 3rd 

Inoltre, vettori indice logiche sono utili:

x[x != "b"]; # without elements that are "b" 

Questo funziona con dataframes anche:

df <- data.frame(number = 1:5, name = letters[1:5]) 

df[df$name != "b", ];  # rows without "b" 

df[df$number %% 2 == 1, ] # rows with odd numbers only 
+0

Il tuo indice logico funziona solo se si ha quel singolo oggetto "b" in un elemento di lista. Non puoi rimuovere, ad esempio, 'x $ b' in questo modo, né puoi rimuovere" b "da un elemento di lista' x [[2]] = c ("b", "k") '. –

16

Rimozione elementi nulli da una lista in sola riga:

x=x[-(which(sapply(x,is.null),arr.ind=TRUE))]

Acclamazioni

+2

Questo codice si rompe quando 'x' è una lista vuota. Utilizzare 'compact' da' plyr' per questa attività. –

+0

Anche se non ci sono valori nulli nella lista, '- (che (sapply (x, is.null), arr.ind = TRUE))' restituisce 'named integer (0)' che lascerà cadere completamente quella riga. – user3055034

24

Ecco come il rimuovere l'ultimo elemento di una lista in R:

x <- list("a", "b", "c", "d", "e") 
x[length(x)] <- NULL 

Se x potrebbe essere un vettore, allora si avrebbe bisogno di creare un nuovo oggetto:

x <- c("a", "b", "c", "d", "e") 
x <- x[-length(x)] 
  • lavoro per liste e vettori
+0

Un caso speciale della risposta di Florian ... – krlmlr

+0

@krlmlr: al contrario, questa soluzione è più generale della risposta di Florian, in quanto è polimorfica nel tipo della raccolta. –

+0

@DanBarowy: Ho sbagliato: questa sembra essere una sintesi della risposta di Chad (quella accettata) e di Florian ... Un breve riassunto, comunque. – krlmlr

-2

È possibile utilizzare which.

x<-c(1:5) 
x 
#[1] 1 2 3 4 5 
x<-x[-which(x==4)] 
x 
#[1] 1 2 3 5 
+18

Questo non è un 'elenco' – GSee

10

Se si dispone di un elenco di nome e si desidera rimuovere un elemento specifico si può provare:

lst <- list(a = 1:4, b = 4:8, c = 8:10) 

if("b" %in% names(lst)) lst <- lst[ - which(names(lst) == "b")] 

Questo farà una lista lst con elementi a, b, c. La seconda riga rimuove l'elemento b dopo aver verificato che esista (per evitare il problema menzionato da @hjv).

o meglio:

lst$b <- NULL 

In questo modo non è un problema per cercare di eliminare un elemento inesistente (ad esempio lst$g <- NULL)

6

C'è il pacchetto rlist (http://cran.r-project.org/web/packages/rlist/index.html) a che fare con vari tipi delle operazioni di lista.

Esempio (http://cran.r-project.org/web/packages/rlist/vignettes/Filtering.html):

library(rlist) 
devs <- 
    list(
    p1=list(name="Ken",age=24, 
     interest=c("reading","music","movies"), 
     lang=list(r=2,csharp=4,python=3)), 
    p2=list(name="James",age=25, 
     interest=c("sports","music"), 
     lang=list(r=3,java=2,cpp=5)), 
    p3=list(name="Penny",age=24, 
     interest=c("movies","reading"), 
     lang=list(r=1,cpp=4,python=2))) 

list.remove(devs, c("p1","p2")) 

risultati in:

# $p3 
# $p3$name 
# [1] "Penny" 
# 
# $p3$age 
# [1] 24 
# 
# $p3$interest 
# [1] "movies" "reading" 
# 
# $p3$lang 
# $p3$lang$r 
# [1] 1 
# 
# $p3$lang$cpp 
# [1] 4 
# 
# $p3$lang$python 
# [1] 2 
+0

Thx per il tuo commento. Ho aggiunto il codice pertinente. – user2030503

5

Non so se hai ancora bisogno di una risposta a questo, ma ho trovato dalle mie limitate (3 settimane di sé -teaching R) esperienza con R che, usando l'assegnazione NULL, è in realtà sbagliato o non ottimale, specialmente se si sta aggiornando dinamicamente un elenco in qualcosa come un ciclo for.

Per essere più precisi, utilizzando

myList[[5]] <- NULL 

getteranno l'errore

myList[[5]] <- NULL : replacement has length zero

o

more elements supplied than there are to replace

Quello che ho trovato a lavorare in modo più coerente è

myList <- myList[[-5]] 
+0

Buona risposta! Tuttavia, penso che '[[-5]]' dovrebbe essere composto da parentesi quadre singole, altrimenti si deseleziona solo il contenuto di quell'elemento dell'elenco, non l'elemento stesso. Bene, almeno usare le doppie parentesi quadre mi dà questo errore: "tenta di selezionare più di un elemento". Allora, quello che funziona per me era: 'myList <- myList [-5]'. –

-1

Che ne dici di questo? Anche in questo caso, utilizzando gli indici

> m <- c(1:5) 
> m 
[1] 1 2 3 4 5 

> m[1:length(m)-1] 
[1] 1 2 3 4 

o

> m[-(length(m))] 
[1] 1 2 3 4 
+1

m è un vettore, non un elenco – C8H10N4O2

+1

Il metodo funziona per gli elenchi, ma OP è fortunato e probabilmente vuole più parentesi: 'm [1: (lunghezza (m) - 1)]' – Gregor

0

Volevo solo aggiungere rapidamente (perché non ho visto in nessuna delle risposte), che, per una lista di nome, si può anche fare l["name"] <- NULL . Per esempio:

l <- list(a = 1, b = 2, cc = 3) 
l['b'] <- NULL 
0

Utilizzando lapply e grep:

lst <- list(a = 1:4, b = 4:8, c = 8:10) 
# say you want to remove a and c 
toremove<-c("a","c") 
lstnew<-lst[-unlist(lapply(toremove, function(x) grep(x, names(lst)))) ] 
#or 
pattern<-"a|c" 
lstnew<-lst[-grep(pattern, names(lst))] 
1

Nel caso di liste di nome trovo quelle funzioni helper utili

member <- function(list,names){ 
    ## return the elements of the list with the input names 
    member..names <- names(list) 
    index <- which(member..names %in% names) 
    list[index]  
} 


exclude <- function(list,names){ 
    ## return the elements of the list not belonging to names 
    member..names <- names(list) 
    index <- which(!(member..names %in% names)) 
    list[index]  
} 
aa <- structure(list(a = 1:10, b = 4:5, fruits = c("apple", "orange" 
)), .Names = c("a", "b", "fruits")) 

> aa 
## $a 
## [1] 1 2 3 4 5 6 7 8 9 10 

## $b 
## [1] 4 5 

## $fruits 
## [1] "apple" "orange" 


> member(aa,"fruits") 
## $fruits 
## [1] "apple" "orange" 


> exclude(aa,"fruits") 
## $a 
## [1] 1 2 3 4 5 6 7 8 9 10 

## $b 
## [1] 4 5