¿Existe una función R para encontrar el índice de un elemento en un vector?


324

En R, tengo un elemento xy un vector v. Quiero encontrar el primer índice de un elemento vque sea igual a x. Sé que una forma de hacerlo es: which(x == v)[[1]]pero parece excesivamente ineficiente. ¿Hay alguna forma más directa de hacerlo?

Para puntos de bonificación, ¿hay una función que funcione si xes un vector? Es decir, debe devolver un vector de índices que indique la posición de cada elemento de xin v.


Como R está optimizado para trabajar con vectores, which(x == v)[[1]]no es tan ineficiente. Es un ==operador de comparación ( ) aplicado a todos los elementos vectoriales y un subconjunto en los índices ( which). Eso es. Nada que deba ser relevante, siempre y cuando no esté ejecutando 10.000 repeticiones en esta función. Otras soluciones tienen gusto matchy Positionpueden no devolver tantos datos como which, pero no son necesariamente más eficientes.
BurninLeo

2
Mi pregunta especificaba que preferiría una función que estaba vectorizada sobre x, y which(x == v)[[1]]no lo es.
Ryan C. Thompson

Respuestas:


461

La función matchfunciona en vectores:

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

matchsolo devuelve el primer encuentro de un partido, como lo solicitó. Devuelve la posición en el segundo argumento de los valores en el primer argumento.

Para la coincidencia múltiple, este %in%es el camino a seguir:

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%devuelve un vector lógico siempre que el primer argumento, con un TRUEvalor de si ese se puede encontrar en el segundo argumento y un valor diferente FALSE.


Creo que un ejemplo con c (2,3,3) yc (1,2,3,4) con coincidencia y% en% sería más instructivo con menos cambios entre los ejemplos. match (c (2,3,3), c (1: 4)) devuelve resultados diferentes de los cuales (c (2,3,3)% en% c (1: 4)) sin necesidad de un primer vector más largo y como muchos cambios de ejemplo a ejemplo. También vale la pena señalar que manejan las no coincidencias de manera muy diferente.
John

1
@John: eso es todo cierto, pero eso no es lo que preguntó el OP. El OP solicitó, a partir de un vector largo, encontrar la primera coincidencia de elementos dados en otro. Y para completar, agregué que si está interesado en todos los índices, tendrá que usar cuál (% en%). Por cierto, no hay razón para borrar su respuesta. Es información válida.
Joris Meys

1
Creo que sería útil enfatizar que el orden de los argumentos es matchimportante si desea el índice de la primera aparición. Para su ejemplo, match(x,c(4,8))da resultados diferentes, lo cual no es súper obvio al principio.
Apitsch

@goldenoslik Ayuda si lees la página de ayuda de match. Todo se explica allí. Pero agregué esa información.
Joris Meys

¡Gracias! ¡Esta solución me salvó el día!
Jinhua Wang

26

la función Positionen funprog {base} también hace el trabajo. Le permite pasar una función arbitraria y devuelve la primera o la última coincidencia.

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


10

Una pequeña nota sobre la eficiencia de los métodos mencionados anteriormente:

 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

Entonces, el mejor es

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

Su punto de referencia se basa en un vector de longitud 12 y, por lo tanto, no es significativo. También en su ejemplo which("Feb" == month.abb)devuelve 2–por [[1]]qué el ?
markus

@markus este código que ("Feb" == month.abb) [[1]] devuelve "2", y este código que (month.abb% en% "Feb") también devuelve "2". Además, no está claro por qué el uso del vector no tiene sentido
Andrii

1
No se trata del vector, sino de su longitud. Debe generar un vector de longitud adecuada y luego hacer un punto de referencia basado en eso. Citando pregunta PO "Sé que una manera de hacer esto es: which(x == v)[[1]] , pero que parece excesivamente ineficiente".
markus

-5

R ha sobrecargado al ==operador de doble igual con un método para encontrar el índice de una aguja en un pajar de vectores. Produce un logicalvector que contiene TRUEvalores para cada coincidencia en el pajar.

Ejemplo:

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

Funciona si ambos son vectores, y puede expandirse para usar también múltiples vectores.


2
El ==operador ya fue mencionado en mi pregunta como una solución ineficiente que no funciona con un vector de agujas.
Ryan C. Thompson

"funciona si ambos son vectores", tal vez, dependiendo de lo que quieras decir ... pero no en el sentido que el OP quería.
Frank

30
En FALSE FALSE TRUE FALSE TRUEeste ejemplo
obtengo

66
Nunca ejecutó esto en R. ==devuelve un vector lógico, no índices. Para eso necesitas which(), como te expliqué hace 7 años.
Joris Meys
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.