Gibt es eine R-Funktion zum Ermitteln des Index eines Elements in einem Vektor?


324

In R habe ich ein Element xund einen Vektor v. Ich möchte den ersten Index eines Elements finden, der vgleich ist x. Ich weiß, dass ein Weg, dies zu tun, ist : which(x == v)[[1]], aber das scheint übermäßig ineffizient. Gibt es einen direkteren Weg, dies zu tun?

Gibt es für Bonuspunkte eine Funktion, die funktioniert, wenn xes sich um einen Vektor handelt? Das heißt, es sollte einen Vektor von Indizes zurückgeben, der die Position jedes Elements von xin angibt v.


Da R für die Arbeit mit Vektoren optimiert ist, which(x == v)[[1]]ist es nicht so sehr ineffizient. Es ist ein Vergleich ( ==) -Operator, der auf alle Vektorelemente angewendet wird, und eine Teilmenge auf den Indizes ( which). Das ist es. Nichts, was relevant sein sollte, solange Sie nicht 10.000 Wiederholungen für diese Funktion ausführen. Andere Lösungen mögen matchund geben Positionmöglicherweise nicht so viele Daten zurück wie which, aber sie sind nicht unbedingt effizienter.
BurninLeo

2
In meiner Frage wurde angegeben, dass ich eine Funktion bevorzugen würde, die gegenüber vektorisiert wurde, und dies which(x == v)[[1]]nicht ist.
Ryan C. Thompson

Antworten:


461

Die Funktion matcharbeitet mit Vektoren:

x <- sample(1:10)
x
# [1]  4  5  9  3  8  1  6 10  7  2
match(c(4,8),x)
# [1] 1 5

matchGibt nur die erste Begegnung eines Spiels zurück, wie Sie es angefordert haben. Es gibt die Position im zweiten Argument der Werte im ersten Argument zurück.

Für mehrere Übereinstimmungen %in%ist der richtige Weg:

x <- sample(1:4,10,replace=TRUE)
x
# [1] 3 4 3 3 2 3 1 1 2 2
which(x %in% c(2,4))
# [1]  2  5  9 10

%in%Gibt einen logischen Vektor zurück, solange das erste Argument vorhanden ist, mit einem TRUEif, wenn dieser Wert im zweiten Argument gefunden werden kann, und einem FALSEanderen.


Ich denke, dass ein Beispiel mit c (2,3,3) und c (1,2,3,4) mit Übereinstimmung und% in% mit weniger Änderungen zwischen den Beispielen lehrreicher wäre. match (c (2,3,3), c (1: 4)) liefert unterschiedliche Ergebnisse, von denen (c (2,3,3)% in% c (1: 4)) ohne einen längeren ersten Vektor und as benötigt wird viele Änderungen von Beispiel zu Beispiel. Es ist auch erwähnenswert, dass sie Nicht-Übereinstimmungen sehr unterschiedlich behandeln.
John

1
@ John: Das ist alles wahr, aber das hat das OP nicht gefragt. Das OP bat ausgehend von einem langen Vektor, die erste Übereinstimmung der in einem anderen angegebenen Elemente zu finden. Der Vollständigkeit halber habe ich hinzugefügt, dass Sie, wenn Sie an allen Indizes interessiert sind, welche verwenden müssen (% in%). Übrigens gibt es keinen Grund, Ihre Antwort zu löschen. Es sind gültige Informationen.
Joris Meys

1
Ich denke, es wäre hilfreich zu betonen, dass die Reihenfolge der Argumente in matchAngelegenheiten, wenn Sie den Index des ersten Auftretens wollen. In Ihrem Beispiel match(x,c(4,8))ergeben sich unterschiedliche Ergebnisse, was zunächst nicht besonders offensichtlich ist.
Apitsch

@goldenoslik Es hilft, wenn Sie die Hilfeseite von lesen match. Dort wird alles erklärt. Aber ich habe diese Information hinzugefügt.
Joris Meys

Vielen Dank! Diese Lösung hat mir den Tag gerettet!
Jinhua Wang

26

Die Funktion Positionin funprog {base} erledigt ebenfalls die Aufgabe. Sie können eine beliebige Funktion übergeben und die erste oder letzte Übereinstimmung zurückgeben.

Position(f, x, right = FALSE, nomatch = NA_integer)


10

Ein kleiner Hinweis zur Effizienz der oben genannten Methoden:

 library(microbenchmark)

  microbenchmark(
    which("Feb" == month.abb)[[1]],
    which(month.abb %in% "Feb"))

  Unit: nanoseconds
   min     lq    mean median     uq  max neval
   891  979.0 1098.00   1031 1135.5 3693   100
   1052 1175.5 1339.74   1235 1390.0 7399  100

Das Beste ist also

    which("Feb" == month.abb)[[1]]

Ihr Benchmark basiert auf einem Vektor der Länge 12 und ist daher nicht aussagekräftig. Auch in Ihrem Beispiel which("Feb" == month.abb)kehrt zurück - 2warum die [[1]]?
Markus

@markus diesen Code, der ("Feb" == month.abb) [[1]] "2" zurückgibt, und diesen Code, der (month.abb% in% "Feb") auch "2" zurückgibt. Auch nicht klar, warum die Verwendung von Vektor nicht sinnvoll ist
Andrii

1
Es geht nicht um den Vektor, sondern um seine Länge. Sie sollten einen Vektor geeigneter Länge generieren und dann einen darauf basierenden Benchmark durchführen. Zitiert aus OPs Frage : „Ich weiß , dass ein Weg , dies zu tun ist: which(x == v)[[1]] , . , Aber das scheint übermäßig ineffizient“
Markus

-5

R hat den Doppelgleichheitsoperator ==mit einer Methode zum Ermitteln des Nadelindex in einem Vektorheuhaufen überladen . Es ergibt einen logicalVektor, der TRUEWerte für jede Übereinstimmung im Heuhaufen enthält.

Beispiel:

haystack <- c(1, 2, 4, 3, 4)
needle <- 4
indices <- needle == haystack
indices
[1] 3  5
haystack[indices]
[1] 4  4

Es funktioniert, wenn beide Vektoren sind, und kann erweitert werden, um auch mehrere Vektoren zu verwenden.


2
Der ==Bediener wurde in meiner Frage bereits als ineffiziente Lösung erwähnt, die mit einem Nadelvektor nicht funktioniert.
Ryan C. Thompson

"Es funktioniert, wenn beide Vektoren sind" - vielleicht, je nachdem, was Sie meinen ... aber nicht in dem Sinne, wie es das OP wollte.
Frank

30
Ich bekomme FALSE FALSE TRUE FALSE TRUEanstelle von Indizes in diesem Beispiel
Sashko Lykhenko

6
Sie haben dies nie in R ausgeführt. ==Gibt einen logischen Vektor zurück, keine Indizes. Dafür brauchst du which(), wie ich vor 7 Jahren erklärt habe.
Joris Meys
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.