Чи існує функція R для знаходження індексу елемента у векторі?


324

У R у мене є елемент xі вектор v. Я хочу знайти перший індекс елемента, vякий дорівнює x. Я знаю, що один із способів зробити це:, which(x == v)[[1]]але це здається надмірно неефективним. Чи є більш прямий спосіб це зробити?

Чи існує бонусна очка функція, яка працює, якщо xце вектор? Тобто він повинен повертати вектор індексів, що вказують положення кожного елемента xв v.


Оскільки R оптимізований для роботи з векторами, which(x == v)[[1]]це не так вже й неефективно. Це один ==оператор порівняння ( ), застосований до всіх векторних елементів та одне підмножина на індекси ( which). Це воно. Нічого, що не повинно бути актуальним, якщо ви не виконаєте 10 000 повторень на цій функції. Інші рішення люблять matchі Positionможуть не повертати стільки даних which, але вони не обов'язково більш ефективні.
BurninLeo

2
У моєму питанні було вказано, що я віддаю перевагу функції, яка була векторизована над x, а which(x == v)[[1]]не є.
Райан К. Томпсон

Відповіді:


461

Функція matchпрацює на векторах:

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

matchповертає лише першу зустріч матчу, як ви просили. Він повертає позицію у другому аргументі значень першого аргументу.

Для кращого узгодження %in%- це спосіб:

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%повертає логічний вектор до тих пір, як перший аргумент, при цьому, TRUEякщо це значення можна знайти у другому аргументі та в FALSEіншому випадку.


Я думаю, що приклад з c (2,3,3) і c (1,2,3,4) з збігом і% у% був би більш повчальним із меншою кількістю змін між прикладами. матч (c (2,3,3), c (1: 4)) повертає різні результати, з яких (c (2,3,3)% у% c (1: 4)) без необхідності більш тривалого першого вектора багато змін від прикладу до прикладу. Варто також зазначити, що вони не по-різному поводяться з невідповідниками.
Джон

1
@John: це все правда, але це не те, що просили ОП. ОП попросила, починаючи з довгого вектора, знайти першу відповідність елементів, поданих в іншому. І для повноти я додав, що якщо вас цікавлять усі показники, вам доведеться використовувати які (% у%). До речі, немає жодної причини видаляти свою відповідь. Це дійсна інформація.
Joris Meys

1
Я думаю, було б корисно підкреслити, що порядок аргументів у matchпитаннях, якщо ви хочете, щоб індекс першого появи. Для вашого прикладу match(x,c(4,8))дає різні результати, що спочатку не надто очевидно.
апічч

@goldenoslik Це допоможе, якщо ви прочитаєте сторінку довідки на match. Там все пояснено. Але я додав цю інформацію.
Joris Meys

Дякую! Це рішення врятувало мені день!
Jinhua Wang

26

функція Positionу funprog {base} також виконує свою роботу. Це дозволяє передавати довільну функцію та повертає першу чи останню відповідність.

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


10

Невелика примітка про ефективність вищезазначених методів:

 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

Отже, найкращий

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

Ваш орієнтир заснований на векторі довжини 12, а отже, не має сенсу. Також у вашому прикладі which("Feb" == month.abb)повертається - 2чому [[1]]?
Маркус

@markus цей код, який ("Feb" == month.abb) [[1]] повертає "2", і цей код, який (month.abb% в% "Feb") також повертає "2". Також не ясно, чому використовувати вектор не має сенсу
Андрій

1
Йдеться не про вектор, а про його довжину. Ви повинні створити вектор відповідної довжини, а потім зробити орієнтир на основі цього. Цитуючи OPS питання «Я знаю , що один з способів зробити це: which(x == v)[[1]] , але здається , що занадто неефективно.»
Маркус

-5

R перевантажив ==оператора подвійних рівних методом знаходження індексу голки у векторній копиці сіна. Він дає logicalвектор, що містить TRUEзначення для кожного сірника в копиці сіна.

Приклад:

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

Він працює, якщо обидва є векторами, і їх також можна розширити, щоб використовувати також декілька векторів.


2
==Оператор вже згадувалося в моєму питанні , як неефективне рішення , яке не працює з вектором голок.
Райан К. Томпсон

"це працює, якщо обидва є векторами" - можливо, залежно від того, що ви маєте на увазі ... але не в тому сенсі, якого хотіла ОП.
Френк

30
Я отримую FALSE FALSE TRUE FALSE TRUEзамість індексів на цьому прикладі
Сашко Лихченко

6
Ви ніколи не запускали це в Р. ==повертає логічний вектор, а не індекси. Для цього вам потрібно which(), як я пояснив 7 років тому.
Йоріс Майс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.