Wie kann ich ein Element aus einer Liste entfernen?


275

Ich habe eine Liste und möchte ein einzelnes Element daraus entfernen. Wie kann ich das machen?

Ich habe versucht nachzuschlagen, was meiner Meinung nach die offensichtlichen Namen für diese Funktion im Referenzhandbuch sind, und ich habe nichts Passendes gefunden.


Abhängig davon, ob Sie es nach Wert entfernen möchten, z. B. "der Wert 5", oder nach Index / Indizes "das Element am Index 5" oder "an den Indizes c (5: 6,10)? Wenn Sie es nach Wert und dort entfernen möchten Sind Duplikate vorhanden, möchten Sie dann nur die Duplikate, das erste oder letzte Vorkommen oder alle entfernen? Ist garantiert, dass die Liste Ihr Element / Ihren Index enthält? Müssen wir den Fall behandeln, in dem die Liste leer ist? Stellen Sie sicher, dass NA bestanden (/ ausgeschlossen) ist. Ist die Liste garantiert flach oder kann sie verschachtelt sein? Wie viele Laters tief?
smci

2
setdiff (myList, elementToRemove)
JStrahl

Antworten:


217

Ich kenne R überhaupt nicht, aber ein bisschen kreatives Googeln hat mich hierher geführt: http://tolstoy.newcastle.edu.au/R/help/05/04/1919.html

Das Schlüsselzitat von dort:

Ich finde keine explizite Dokumentation für R zum Entfernen von Elementen aus Listen, aber Versuch und Irrtum sagen es mir

myList [[5]] <- NULL

entfernt das 5. Element und "schließt" dann das Loch, das durch das Löschen dieses Elements verursacht wurde. Dadurch werden die Indexwerte gedämpft. Daher muss ich beim Löschen von Elementen vorsichtig sein. Ich muss von der Rückseite der Liste nach vorne arbeiten.

Eine Antwort auf diesen Beitrag später im Thread lautet:

Informationen zum Löschen eines Elements einer Liste finden Sie unter R FAQ 7.1

Und der relevante Abschnitt der R-FAQ lautet:

... Setzen Sie x [i] oder x [[i]] nicht auf NULL, da dadurch die entsprechende Komponente aus der Liste entfernt wird.

Was Ihnen (etwas rückwärts) zu sagen scheint, wie Sie ein Element entfernen können.

Hoffe das hilft oder führt dich zumindest in die richtige Richtung.


5
Danke, mylist [i] <- NULL ist genau der richtige Weg.
David Locke

37
Das hat bei mir nicht funktioniert. Ich bekomme:Error in list[length(list)] <- NULL : replacement has length zero
wfbarksdale

3
@Aleksandr Levchucks Beitrag zeigte mir, dass ich tatsächlich mit einem Vektor zu tun hatte und ein neues Objekt erstellen musste
wfbarksdale

209

Wenn Sie die Liste nicht direkt ändern möchten (z. B. um die Liste mit einem an eine Funktion entfernten Element zu übergeben), können Sie die Indizierung verwenden: Negative Indizes bedeuten "Dieses Element nicht einschließen".

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

x[-2];       # without 2nd element

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

Auch logische Indexvektoren sind nützlich:

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

Dies funktioniert auch mit Datenrahmen:

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

4
Ihr logischer Index funktioniert nur, wenn Sie das einzelne Element "b" in einem Listenelement haben. Sie können beispielsweise weder auf x$bdiese Weise entfernen noch "b" aus einem Listenelement entfernen x[[2]] = c("b","k") .
Carl Witthoft

In Bezug auf einzelne oder mehrere Elemente: Sie können sie %in%zum Testen mehrerer Elemente verwenden. Ich bin mir nicht sicher, was Sie unter "x $ b kann nicht entfernt werden" verstehen - meinen Sie das Entfernen der gesamten Spalte b?
Florian Jenn

30

So entfernen Sie das letzte Element einer Liste in R:

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

Wenn x ein Vektor sein könnte, müssten Sie ein neues Objekt erstellen:

x <- c("a", "b", "c", "d", "e")
x <- x[-length(x)]
  • Arbeiten Sie für Listen und Vektoren

@krlmlr: Im Gegenteil, diese Lösung ist allgemeiner als Florians Antwort, da sie in der Art der Sammlung polymorph ist.
Dan Barowy

@ DanBarowy: Ich habe mich geirrt: Dies scheint eine Synthese aus Tschads Antwort (der akzeptierten) und Florians zu sein ... Eine gute kurze Zusammenfassung.
krlmlr

19

Entfernen von Null-Elementen aus einer einzeiligen Liste:

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

Prost


2
Dieser Code bricht ab, wenn xeine leere Liste vorliegt . Verwenden compactvon plyrfür diese Aufgabe statt.
Richie Cotton

Auch wenn die Liste keine Nullen enthält, wird -(which(sapply(x,is.null),arr.ind=TRUE))zurückgegeben, named integer(0)wodurch diese Zeile vollständig gelöscht wird.
user3055034

17

Ich möchte hinzufügen, dass Sie, wenn es sich um eine benannte Liste handelt , diese einfach verwenden können within.

l <- list(a = 1, b = 2)    
> within(l, rm(a))
$b
[1] 2

So können Sie die ursprüngliche Liste überschreiben

l <- within(l, rm(a)) 

um das benannte Element aaus der Liste zu entfernen l.


1
Mehrfach machenwithin(l, rm(a, b))
Vlad

16

Wenn Sie eine benannte Liste haben und ein bestimmtes Element entfernen möchten, können Sie Folgendes versuchen:

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

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

Dadurch wird eine Liste machen lstmit Elementen a, b, c. In der zweiten Zeile wird das Element entfernt, bnachdem überprüft wurde, ob es vorhanden ist (um das erwähnte Problem @hjv zu vermeiden).

oder besser:

lst$b <- NULL

Auf diese Weise ist es kein Problem , zu versuchen , ein nicht vorhandenes Element zu löschen (zB lst$g <- NULL)


10

Es gibt das rlist-Paket ( http://cran.r-project.org/web/packages/rlist/index.html ), das sich mit verschiedenen Arten von Listenoperationen befasst .

Beispiel ( 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"))

Ergebnisse 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

Wie kann man die Python- oder Lang-Elemente in diesem Beispiel entfernen?
Arthur Yip

9

Ich weiß nicht, ob Sie noch eine Antwort darauf benötigen, aber ich habe aus meiner begrenzten Erfahrung (3 Wochen Autodidakt R) mit R herausgefunden, dass die Verwendung der NULLAufgabe tatsächlich falsch oder nicht optimal ist, insbesondere wenn Sie dynamisch aktualisieren eine Liste in so etwas wie einer for-Schleife.

Genauer gesagt mit

myList[[5]] <- NULL

wird den Fehler werfen

myList [[5]] <- NULL: Ersetzung hat die Länge Null

oder

Es werden mehr Elemente geliefert, als ersetzt werden müssen

Was ich als konsequenter empfand, ist

myList <- myList[[-5]]

1
Gute Antwort! Ich denke jedoch, dass es [[-5]]sich um einzelne eckige Klammern handeln sollte, da Sie sonst nur den Inhalt dieses Listenelements abwählen, nicht das Element selbst. Nun, zumindest die Verwendung von doppelten eckigen Klammern gibt mir den Fehler: "Versuch, mehr als ein Element auszuwählen". Was für mich funktioniert war dann : myList <- myList[-5].
n1k31t4

4

Ich wollte nur schnell hinzufügen (weil ich es in keiner der Antworten gesehen habe), dass Sie für eine benannte Liste auch tun können l["name"] <- NULL. Zum Beispiel:

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

4

Verwenden Sie -(negatives Vorzeichen) zusammen mit der Position des Elements. Wenn das dritte Element entfernt werden soll, verwenden Sie es alsyour_list[-3]

Eingang

my_list <- list(a = 3, b = 3, c = 4, d = "Hello", e = NA)
my_list
# $`a`
# [1] 3

# $b
# [1] 3

# $c
# [1] 4

# $d
# [1] "Hello"

# $e
# [1] NA

Entfernen Sie ein einzelnes Element aus der Liste

 my_list[-3]
 # $`a`
 # [1] 3

 # $b
 # [1] 3

 # $d
 # [1] "Hello"

 # $e
 [1] NA

Entfernen Sie mehrere Elemente aus der Liste

 my_list[c(-1,-3,-2)]
 # $`d`
 # [1] "Hello"

 # $e
 # [1] NA

 my_list[c(-3:-5)]
 # $`a`
 # [1] 3

 # $b
 # [1] 3

 my_list[-seq(1:2)]
 # $`c`
 # [1] 4

 # $d
 # [1] "Hello"

 # $e
 # [1] NA

2

Bei benannten Listen finde ich diese Hilfsfunktionen nützlich

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

0

Mit lapply und 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

Wie wäre es damit? Wieder mit Indizes

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

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

oder

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

1
m ist ein Vektor, keine Liste
C8H10N4O2

1
Die Methode funktioniert für Listen, aber OP hat Glück und möchte wahrscheinlich noch einige Klammern:m[1:(length(m) - 1)]
Gregor Thomas

-1

Wenn Sie numerische Indizes vermeiden möchten, können Sie verwenden

a <- setdiff(names(a),c("name1", ..., "namen"))

Namen namea...namenaus a löschen . Dies funktioniert für Listen

> l <- list(a=1,b=2)
> l[setdiff(names(l),"a")]
$b
[1] 2

sowie für Vektoren

> v <- c(a=1,b=2)
> v[setdiff(names(v),"a")]
b 
2

-2

Sie können verwenden which.

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

20
Das ist keinlist
GSee
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.