Wie lösche ich mehrere Werte aus einem Vektor?


125

Ich habe einen Vektor wie: a = c(1:10)und ich muss mehrere Werte entfernen, wie:2, 3, 5

Wie lösche ich diese Zahlen (sie sind NICHT die Positionen im Vektor) im Vektor?

Im Moment schleife ich den Vektor und mache so etwas wie:

a[!a=NUMBER_TO_REMOVE]

Aber ich denke, es gibt eine Funktion, die das automatisch macht.

Antworten:


192

Der %in%Operator teilt Ihnen mit, welche Elemente zu den zu entfernenden Zahlen gehören:

> a <- sample (1 : 10)
> remove <- c (2, 3, 5)
> a
 [1] 10  5  2  7  1  6  3  4  8  9
> a %in% remove
 [1] FALSE  TRUE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE
> a [! a %in% remove]
 [1] 10  7  1  6  4  8  9

Beachten Sie, dass dadurch unvergleichliche Elemente (wie NAoder Inf)auch) stillschweigend entfernt werden (während doppelte Werte beibehalten werden, asolange sie nicht in aufgeführt sind remove).

  • Wenn aes unvergleichliche Elemente enthalten kann, dies aber removenicht wird, können wir es verwenden matchund es anweisen, 0für Nichtübereinstimmungen und unvergleichbare Daten zurückzukehren ( %in%ist eine bequeme Abkürzung für match):

    > a <- c (a, NA, Inf)
    > a
     [1]  10   5   2   7   1   6   3   4   8   9  NA Inf
    > match (a, remove, nomatch = 0L, incomparables = 0L)
     [1] 0 3 1 0 0 0 2 0 0 0 0 0
    > a [match (a, remove, nomatch = 0L, incomparables = 0L) == 0L]
    [1]  10   7   1   6   4   8   9  NA Inf

    incomparables = 0wird nicht benötigt, da unvergleichliche Daten sowieso nicht übereinstimmen, aber ich würde es aus Gründen der Lesbarkeit einschließen.
    Dies ist übrigens das, was setdiffintern geschieht (aber ohne die uniqueDuplikate wegzuwerfen, in adenen nicht enthalten sind remove).

  • Wenn es removeunvergleichliche Elemente enthält, müssen Sie diese einzeln prüfen, z

    if (any (is.na (remove))) 
      a <- a [! is.na (a)]

    (Dies unterscheidet nicht NAvonNaN aber das R-Handbuch warnt trotzdem davor, dass man sich nicht darauf verlassen sollte, einen Unterschied zwischen ihnen zu haben.)

    Für Inf/ müssen -InfSie beide signund überprüfenis.finite


1
setdiffist besser, da es alles in einer Operation erledigt und nur einmal auf den geänderten Vektor verweist.
Olexa

1
@Olexa: Mengenunterschied ist nicht immer dasselbe wie das Entfernen aller Vorkommen eines bestimmten Satzes von Zahlen aus einem Vektor: Es werden Duplikate entfernt a, die nicht removeebenfalls vorhanden sind. Wenn das kein Problem ist, können Sie auch verwenden setdiff. setdiffÜbrigens, verwendet, matchfür die %in%eine Verknüpfung ist.
cbeleites unglücklich mit SX

97

Sie können verwenden setdiff.

Gegeben

a <- sample(1:10)
remove <- c(2, 3, 5)

Dann

> a
 [1] 10  8  9  1  3  4  6  7  2  5
> setdiff(a, remove)
[1] 10  8  9  1  4  6  7

1
Sehr nützlich, wenn adas Ergebnis einer anderen Funktion ist, so dass Sie Dinge in einer Zeile anstelle von 3 und einer temporären Variablen
tun

14
Dies führt zu anderen Ergebnissen als die %in%Lösung, wenn der Eingabevektor Duplikate enthält (in diesem Fall setdiffwird nur die eindeutige Menge zurückgegeben , dh ohne Duplikate)
Talat

2
@docendodiscimus: fsetdiffof data.tablepackage hat ein allFlag (Standard F), mit dem Duplikate im Eingabevektor beibehalten werden können.
Jürgen

9

Sie können dies wie folgt tun:

> x<-c(2, 4, 6, 9, 10) # the list
> y<-c(4, 9, 10) # values to be removed

> idx = which(x %in% y ) # Positions of the values of y in x
> idx
[1] 2 4 5
> x = x[-idx] # Remove those values using their position and "-" operator
> x
[1] 2 6

In Kürze

> x = x[ - which(x %in% y)]

1
Was Sie in Ihrem Beispiel als Liste bezeichnen, ist ein Vektor, oder?
Patrick

Ja, ich meine den Vektor. Danke für den Kommentar.
Ykpemre

Hier besteht keine Notwendigkeit which. Es ist im Grunde das gleiche wie die Antwort von @cbeleites.
David Arenburg

Ja, es ist ähnlich, aber in einigen Gesichtspunkten unterschiedlich. whichGibt Indizes von TRUE-Werten zurück. Das Minuszeichen kann also verwendet werden, um "die anderen Indizes als diese Indizes" zu sagen. Auch whichist besser lesbar, da es näher an der natürlichen Sprache ist.
Ykpemre

4

anstatt

x <- x[! x %in% c(2,3,5)]

Mit den Paketen purrrund magrittrkönnen Sie:

your_vector %<>% discard(~ .x %in% c(2,3,5))

dies ermöglicht subsetting die Vektornamen nur einmal verwenden. Und du kannst es in Rohren verwenden :)


Können Sie bitte Ihre letzte Aussage zur Länge des Variablennamens erläutern? Warum magst du das nicht? Warum ist besser als der andere Weg? Oder entfernen Sie diesen Absatz, da er nicht mit dem Hauptproblem / der Hauptfrage zusammenhängt.
Rodrigoap

2

Zuerst können wir einen neuen Operator definieren,

"%ni%" = Negate( "%in%" )

Dann ist es wie x nicht in entfernen

x <- 1:10
remove <- c(2,3,5)
x <- x[ x %ni% remove ]

oder warum zum Entfernen gehen, gehen Sie direkt

x <- x[ x %ni% c(2,3,5)]

3
Die Frage besagt ausdrücklich, dass 2, 3 und 5 keine Positionen im Vektor sind.
Blakeoft

1

AKTUALISIEREN:

Alle oben genannten Antworten funktionieren nicht für die wiederholten Werte. Die Antwort von @ BenBolker unter Verwendung eines duplicated()Prädikats löst Folgendes :

full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]

Ursprüngliche Antwort: Hier schreibe ich eine kleine Funktion dafür:

exclude_val<-function(full_vector,searched_vector){

      found=c()

      for(i in full_vector){  

        if(any(is.element(searched_vector,i))){
          searched_vector[(which(searched_vector==i))[1]]=NA
        }
        else{
          found=c(found,i)
        }
    }

    return(found)
}

Also, sagen wir mal full_vector=c(1,2,3,4,1)undsearched_vector=c(1,2,3) .

exclude_val(full_vector,searched_vector)wird zurückkehren (4,1), jedoch werden die obigen Antworten nur zurückgeben (4).


1
was ist mit full_vector[!full_vector %in% searched_vector | duplicated(full_vector)]?
Ben Bolker

@ BenBolker ah Ich wusste nicht, dass "dupliziert" Prädikat: ((was nun, soll ich meine Antwort löschen oder ändern, um stattdessen nur Ihre anzuzeigen?
Özgür

@ BenBolker, deine Lösung ist falsch; versuchen Sie einfach: full_vector = c(1,1,1,2,3); searched_vector = c(1,1,3);- das ergibt 1, 1, 2anstelle der richtigen Antwort 1, 2.
fnl

Nur um eine mögliche, korrekte Lösung für wiederholte Werte hinzuzufügen:removeif <- function(from, where) { for (i in where) if (i %in% from) {from = from[-match(i, from)]}; from}
fnl

1
q <- c(1,1,2,2,3,3,3,4,4,5,5,7,7)
rm <- q[11]
remove(rm)
q
q[13] = NaN
q
q %in% 7

Dies setzt die 13 in einem Vektor auf keine Zahl (NAN), die falsches Entfernen anzeigt (q [c (11,12,13)]). Wenn Sie dies versuchen, werden Sie feststellen, dass die Entfernungsfunktion bei der Vektornummer nicht funktioniert. Sie entfernen den gesamten Vektor, aber möglicherweise kein einzelnes Element.


1

Es gibt auch subsetDinge, die manchmal nützlich sein können:

a <- sample(1:10)
bad <- c(2, 3, 5)

> subset(a, !(a %in% bad))
[1]  9  7 10  6  8  1  4
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.