Существует ли функция 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) с соответствием и% в% был бы более поучительным с меньшим количеством изменений между примерами. Функция match (c (2,3,3), c (1: 4)) возвращает различные результаты, из которых (c (2,3,3)% в% c (1: 4)) без использования более длинного первого вектора и как много изменений от примера к примеру. Стоит также отметить, что они обрабатывают несоответствия совсем по-другому.
Джон
1
@ Джон: это все правда, но это не то, что спросил ОП. ОП попросил, начиная с длинного вектора, найти первое совпадение элементов, приведенных в другом. А для полноты я добавил, что если вас интересуют все индексы, вам придется использовать какой (% в%). Кстати, нет причин удалять ваш ответ. Это действительная информация.
Йорис Мейс
1
Я думаю, что было бы полезно подчеркнуть, что порядок аргументов в matchвопросах, если вы хотите индекс первого вхождения. Для вашего примера match(x,c(4,8))дает разные результаты, что на первый взгляд не очень очевидно.
apitsch
@goldenoslik Это помогает, если вы читаете страницу помощи match. Там все объяснено. Но я добавил эту информацию.
Joris
Спасибо! Это решение спасло мой день!
Цзиньхуа Ван,
26

функция Positionв funprog {base} также делает свою работу. Это позволяет вам передавать произвольную функцию и возвращает первое или последнее совпадение.

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

pedroteixeira
источник
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

Он работает, если оба являются векторами, и может быть расширен для использования нескольких векторов.

hiten2
источник
2
==Оператор уже упоминалось в моем вопросе , как неэффективное решение , которое не работает с вектором игл.
Райан К. Томпсон
«это работает, если оба являются векторами» - возможно, в зависимости от того, что вы имеете в виду ... но не в том смысле, в котором хотел ОП.
Франк
30
Я получаю FALSE FALSE TRUE FALSE TRUEвместо индексов в этом примере
Сашка Лыхенко
6
Вы никогда не запускали это в R. ==возвращает логический вектор, а не индексы. Для этого вам нужно which(), как я объяснил 7 лет назад.
Йорис Мейс