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.


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.


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)


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]]

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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.