Esiste una funzione R per trovare l'indice di un elemento in un vettore?


324

In R, ho un elemento xe un vettore v. Voglio trovare il primo indice di un elemento vche è uguale a x. So che un modo per farlo è:, which(x == v)[[1]]ma sembra eccessivamente inefficiente. C'è un modo più diretto per farlo?

Per i punti bonus, esiste una funzione che funziona se xè un vettore? Cioè, dovrebbe restituire un vettore di indici che indica la posizione di ciascun elemento di xin v.


Poiché R è ottimizzato per funzionare con i vettori, which(x == v)[[1]]non è molto inefficiente. È un ==operatore di confronto ( ) applicato a tutti gli elementi vettoriali e un sottoinsieme sugli indici ( which). Questo è tutto. Nulla che dovrebbe essere rilevante, purché non si eseguano 10.000 ripetizioni su questa funzione. Altre soluzioni come matche Positionpotrebbero non restituire il maggior numero di dati which, ma non sono necessariamente più efficienti.
BurninLeo,

2
La mia domanda specificava che avrei preferito una funzione che era vettoriale su x, e which(x == v)[[1]]non lo è.
Ryan C. Thompson,

Risposte:


461

La funzione matchfunziona su vettori:

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

matchrestituisce solo il primo incontro di una partita, come richiesto. Restituisce la posizione nel secondo argomento dei valori nel primo argomento.

Per la corrispondenza multipla, %in%è la strada da percorrere:

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%restituisce un vettore logico fino al primo argomento, con un TRUEse quel valore può essere trovato nel secondo argomento e un FALSEaltro.


Penso che un esempio con c (2,3,3) e c (1,2,3,4) con entrambi match e% in% sarebbe più istruttivo con meno cambiamenti tra gli esempi. match (c (2,3,3), c (1: 4)) restituisce risultati diversi da cui (c (2,3,3)% in% c (1: 4)) senza bisogno di un primo vettore più lungo e come molte modifiche da esempio a esempio. Vale anche la pena notare che gestiscono le non partite in modo molto diverso.
John,

1
@John: è tutto vero, ma non è quello che l'OP ha chiesto. L'OP ha chiesto, a partire da un vettore lungo, di trovare la prima corrispondenza di elementi fornita in un'altra. E per completezza, ho aggiunto che se sei interessato a tutti gli indici, dovrai usare quale (% in%). A proposito, non c'è motivo di eliminare la risposta. Sono informazioni valide.
Joris Meys,

1
Penso che sarebbe utile sottolineare che l'ordine degli argomenti in matchmateria se si desidera l'indice della prima occorrenza. Per il tuo esempio, match(x,c(4,8))dà risultati diversi, che all'inizio non è molto ovvio.
apitsch,

@goldenoslik Aiuta se leggi la pagina di aiuto di match. È tutto spiegato lì. Ma ho aggiunto quella informazione.
Joris Meys,

Grazie! Questa soluzione mi ha salvato la giornata!
Jinhua Wang,

26

anche la funzione Positionin funprog {base} fa il lavoro. Ti consente di passare una funzione arbitraria e restituisce la prima o l'ultima corrispondenza.

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


10

Una piccola nota sull'efficienza dei metodi sopra menzionati:

 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

Quindi, il migliore è

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

Il benchmark si basa su un vettore di lunghezza 12 e quindi non significativo. Anche nel tuo esempio which("Feb" == month.abb)restituisce 2-perché il [[1]]?
markus,

@markus questo codice che ("Feb" == month.abb) [[1]] restituisce "2", e questo codice che (month.abb% in% "Feb") restituisce anche "2". Inoltre, non è chiaro perché l'utilizzo del vettore non sia significativo
Andrii,

1
Non si tratta del vettore, ma della sua lunghezza. Dovresti generare un vettore di lunghezza appropriata e quindi fare un benchmark basato su quello. Citando dal PO domanda "So che un modo per farlo è: which(x == v)[[1]] , ma che sembra troppo inefficiente."
markus,

-5

R ha sovraccaricato l' ==operatore del doppio uguale con un metodo per trovare l'indice di un ago in un pagliaio vettoriale. Produce un logicalvettore, contenente TRUEvalori per ogni partita nel pagliaio.

Esempio:

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

Funziona se entrambi sono vettori e può essere espanso per utilizzare anche più vettori.


2
L' ==operatore è già stato menzionato nella mia domanda come una soluzione inefficiente che non funziona con un vettore di aghi.
Ryan C. Thompson,

"funziona se entrambi sono vettori" - forse, a seconda di cosa intendi ... ma non nel senso che l'OP voleva.
Frank,

30
In FALSE FALSE TRUE FALSE TRUEquesto esempio ottengo invece gli indici
Sashko Lykhenko,

6
Non hai mai eseguito questo in R. ==restituisce un vettore logico, non indici. Per questo è necessario which(), come ho spiegato 7 anni fa.
Joris Meys,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.