Czy istnieje funkcja R do znajdowania indeksu elementu w wektorze?

324

W R mam element xi wektor v. Chcę znaleźć pierwszy indeks elementu, vktóry jest równy x. Wiem, że jednym ze sposobów jest: which(x == v)[[1]]ale wydaje się to nadmiernie nieefektywne. Czy istnieje bardziej bezpośredni sposób?

Czy w przypadku punktów bonusowych działa funkcja, która xjest wektorem? Oznacza to, że powinien zwrócić wektor wskaźników wskazujących pozycję każdego elementu xw v.

Ryan C. Thompson
źródło
Ponieważ R jest zoptymalizowany do pracy z wektorami, which(x == v)[[1]]nie jest tak bardzo nieefektywny. Jest to jeden ==operator porównania ( ) zastosowany do wszystkich elementów wektorowych i jeden podzbiór indeksów ( which). Otóż ​​to. Nic, co nie powinno być istotne, dopóki nie uruchomisz 10.000 powtórzeń dla tej funkcji. Inne rozwiązania takie jak matchi Positionmogą nie zwracać tylu danych which, ale niekoniecznie są bardziej wydajne.
BurninLeo,
2
Moje pytanie określiło, że wolę funkcję, która jest wektoryzowana niż x, a which(x == v)[[1]]nie jest.
Ryan C. Thompson,

Odpowiedzi:

461

Funkcja matchdziała na wektorach:

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

matchzwraca tylko pierwsze spotkanie z meczu, tak jak prosiłeś. Zwraca pozycję w drugim argumencie wartości w pierwszym argumencie.

W przypadku wielokrotnego dopasowywania %in%jest to droga:

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%zwraca wektor logiczny tak długo, jak pierwszy argument, z wartością TRUEif można znaleźć w drugim argumencie i w FALSEprzeciwnym razie.

Joris Meys
źródło
Myślę, że przykład z c (2,3,3) i c (1,2,3,4) z dopasowaniem i% w% byłby bardziej pouczający z mniejszą liczbą zmian między przykładami. dopasowanie (c (2,3,3), c (1: 4)) zwraca różne wyniki, z których (c (2,3,3)% w% c (1: 4)) nie wymaga dłuższego pierwszego wektora i jako wiele zmian z przykładu na przykład. Warto również zauważyć, że bardzo różnie radzą sobie z dopasowaniami.
John
1
@John: to wszystko prawda, ale nie o to prosił OP. OP poprosił, zaczynając od długiego wektora, o znalezienie pierwszego dopasowania elementów podanych w innym. I dla kompletności dodałem, że jeśli jesteś zainteresowany wszystkimi indeksami, będziesz musiał użyć tego (% w%). BTW, nie ma powodu, aby usunąć swoją odpowiedź. To ważna informacja.
Joris Meys,
1
Myślę, że warto podkreślić, że kolejność argumentów ma matchznaczenie, jeśli chcesz indeks pierwszego wystąpienia. Na przykład match(x,c(4,8))daje różne wyniki, co na początku nie jest zbyt oczywiste.
apitsch
@goldenoslik To pomaga, jeśli czytasz stronę pomocy match. Wszystko jest tam wyjaśnione. Ale dodałem tę informację.
Joris Meys,
Dzięki! To rozwiązanie uratowało mi dzień!
Jinhua Wang,
26

funkcja Positionw funprog {base} również wykonuje tę pracę. Pozwala przekazać dowolną funkcję i zwraca pierwsze lub ostatnie dopasowanie.

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

pedroteixeira
źródło
10

Mała uwaga na temat skuteczności wyżej wymienionych metod:

 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

Więc najlepszy jest

    which("Feb" == month.abb)[[1]]
Andrii
źródło
Twój test porównawczy opiera się na wektorze o długości 12 i dlatego nie ma znaczenia. Również w twoim przykładzie which("Feb" == month.abb)zwraca - 2dlaczego [[1]]?
markus
@markus ten kod, który („Feb” == month.abb) [[1]] zwraca „2”, a ten kod, który (month.abb% w% „Feb”) również zwraca „2”. Nie jest też jasne, dlaczego użycie wektora nie ma znaczenia
Andrii
1
Nie chodzi o wektor, ale o jego długość. Powinieneś wygenerować wektor o odpowiedniej długości, a następnie wykonać na tej podstawie test porównawczy. Cytując z OPS pytanie „Wiem, że jednym ze sposobów, aby to zrobić, to: which(x == v)[[1]] , ., Ale to wydaje się nadmiernie nieefektywne”
markus
-5

R przeciążył ==operatora podwójnej równości metodą wyszukiwania indeksu igły w wektorowym stogu siana. Daje logicalwektor zawierający TRUEwartości dla każdego dopasowania w stogu siana.

Przykład:

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

Działa, jeśli oba są wektorami, i można je rozszerzyć, aby używały również wielu wektorów.

hiten2
źródło
2
==Operator już wspomniano w moje pytanie jako nieefektywnego rozwiązania, które nie działa z wektorem igieł.
Ryan C. Thompson,
„działa, jeśli oba są wektorami” - być może, w zależności od tego, co masz na myśli ... ale nie w takim znaczeniu, w jakim chciał OP.
Frank
30
Dostaję FALSE FALSE TRUE FALSE TRUEzamiast wskaźników w tym przykładzie
Sashko Lykhenko
6
Nigdy nie uruchomiłeś tego w R. ==Zwraca wektor logiczny, a nie indeksy. Do tego potrzebujesz which(), jak wyjaśniłem 7 lat temu.
Joris Meys