Existe uma função R para encontrar o índice de um elemento em um vetor?


324

Em R, eu tenho um elemento xe um vetor v. Eu quero encontrar o primeiro índice de um elemento em vque é igual a x. Eu sei que uma maneira de fazer isso é:, which(x == v)[[1]]mas isso parece excessivamente ineficiente. Existe uma maneira mais direta de fazer isso?

Para pontos de bônus, existe uma função que funciona se xfor um vetor? Ou seja, ele deve retornar um vetor de índices indicando a posição de cada elemento de xin v.


Como R é otimizado para trabalhar com vetores, which(x == v)[[1]]não é tão ineficiente. É um ==operador de comparação ( ) aplicado a todos os elementos vetoriais e um subconjunto nos índices ( which). É isso aí. Nada que deva ser relevante, desde que você não esteja executando 10.000 repetições nesta função. Outras soluções gostam matche Positionpodem não retornar tantos dados quanto which, mas não são necessariamente mais eficientes.
BurninLeo

2
Minha pergunta especificava que eu preferiria uma função vetorizada sobre x, e which(x == v)[[1]]não é.
Ryan C. Thompson

Respostas:


461

A função matchfunciona em vetores:

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

matchretorna apenas o primeiro encontro de uma partida, conforme solicitado. Retorna a posição no segundo argumento dos valores no primeiro argumento.

Para a correspondência múltipla, %in%é o caminho 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%retorna um vetor lógico contanto que o primeiro argumento, com um TRUEse esse valor puder ser encontrado no segundo argumento e um FALSEcaso contrário.


Penso que um exemplo com c (2,3,3) ec (1,2,3,4) com ambos match e% em% seria mais instrutivo com menos alterações entre os exemplos. match (c (2,3,3), c (1: 4)) retorna resultados diferentes dos quais (c (2,3,3)% em% c (1: 4)) sem precisar de um primeiro vetor mais longo e como muitas mudanças de exemplo para exemplo. Também vale a pena notar que eles lidam com não-correspondências de maneira muito diferente.
John John

1
@ John: isso é tudo verdade, mas não é isso que o OP pediu. O OP pediu, partindo de um vetor longo, para encontrar a primeira correspondência de elementos apresentada em outro. E, para completar, acrescentei que, se você estiver interessado em todos os índices, precisará usar qual (% em%). BTW, não há razão para excluir sua resposta. É informação válida.
Joris Meys

1
Eu acho que seria útil enfatizar que a ordem dos argumentos é matchimportante se você quiser o índice da primeira ocorrência. Para o seu exemplo, match(x,c(4,8))fornece resultados diferentes, o que não é super óbvio a princípio.
apitsch

@goldenoslik Ajuda se você ler a página de ajuda de match. Está tudo explicado lá. Mas eu adicionei essa informação.
precisa

Obrigado! Esta solução salvou o meu dia!
Jinhua Wang

26

a função Positionno funprog {base} também faz o trabalho. Ele permite que você passe uma função arbitrária e retorna a primeira ou a última correspondência.

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


10

Uma pequena observação sobre a eficiência dos métodos acima mencionados:

 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

Então, o melhor é

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

Sua referência é baseada em um vetor de comprimento 12 e, portanto, não é significativa. Também no seu exemplo which("Feb" == month.abb)retorna - por que 2o [[1]]?
Markus

@markus este código que ("Feb" == month.abb) [[1]] retorna "2", e esse código que (month.abb% em% "Feb") também retorna "2". Além disso, não está claro por que usar vector não é significativo
Andrii

1
Não é sobre o vetor, mas sobre seu comprimento. Você deve gerar um vetor de comprimento apropriado e, em seguida, fazer uma referência com base nisso. Citando questão PO "Eu sei que uma maneira de fazer isso é: which(x == v)[[1]] , ., Mas que parece excessivamente ineficiente"
markus

-5

R sobrecarregou o ==operador double equals com um método de encontrar o índice de uma agulha em um palheiro vetorial. Ele gera um logicalvetor, contendo TRUEvalores para cada correspondência no palheiro.

Exemplo:

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

Funciona se ambos forem vetores e pode ser expandido para usar vários vetores também.


2
O ==operador já foi mencionado na minha pergunta como uma solução ineficiente que não funciona com um vetor de agulhas.
Ryan C. Thompson

"funciona se ambos são vetores" - talvez, dependendo do que você quer dizer ... mas não no sentido que o OP queria.
19416 Frank

30
Eu recebo em FALSE FALSE TRUE FALSE TRUEvez de índices neste exemplo
Sashko Lykhenko

6
Você nunca executou isso em R. ==retorna um vetor lógico, não índices. Para isso você precisa which(), como expliquei há 7 anos.
Joris Meys
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.