Apakah ada fungsi R untuk menemukan indeks elemen dalam vektor?

324

Dalam R, saya memiliki elemen xdan vektor v. Saya ingin mencari indeks pertama dari suatu elemen vyang sama dengan x. Saya tahu bahwa salah satu cara untuk melakukan ini adalah:, which(x == v)[[1]]tetapi tampaknya terlalu tidak efisien. Apakah ada cara yang lebih langsung untuk melakukannya?

Untuk poin bonus, apakah ada fungsi yang berfungsi jika xvektor? Artinya, harus mengembalikan vektor indeks yang menunjukkan posisi setiap elemen xdalam v.

Ryan C. Thompson
sumber
Karena R dioptimalkan untuk bekerja dengan vektor, which(x == v)[[1]]tidak begitu tidak efisien. Ini satu perbandingan ( ==) operator yang diterapkan untuk semua elemen vektor dan satu subset pada indeks ( which). Itu dia. Tidak ada yang seharusnya relevan, selama Anda tidak menjalankan 10.000 pengulangan pada fungsi ini. Solusi lain suka matchdan Positionmungkin tidak mengembalikan sebanyak mungkin data which, tetapi tidak selalu lebih efisien.
BurninLeo
2
Pertanyaan saya menentukan bahwa saya lebih suka fungsi yang di-vektor-kan lebih dari x, dan which(x == v)[[1]]tidak.
Ryan C. Thompson

Jawaban:

461

Fungsi ini matchbekerja pada vektor:

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

matchhanya mengembalikan pertemuan pertama pertandingan, seperti yang Anda minta. Ini mengembalikan posisi dalam argumen kedua dari nilai-nilai dalam argumen pertama.

Untuk pencocokan berganda, %in%adalah caranya:

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%mengembalikan vektor logis selama argumen pertama, dengan nilai TRUEjika itu dapat ditemukan dalam argumen kedua dan FALSEsebaliknya.

Joris Meys
sumber
Saya pikir contoh dengan c (2,3,3) dan c (1,2,3,4) dengan kecocokan dan% dalam% akan lebih instruktif dengan lebih sedikit perubahan di antara contoh. pertandingan (c (2,3,3), c (1: 4)) menghasilkan hasil yang berbeda dari yang (c (2,3,3)% dalam% c (1: 4)) tanpa perlu vektor pertama yang lebih panjang dan sebagai banyak perubahan dari contoh ke contoh. Perlu juga dicatat bahwa mereka menangani ketidakcocokan sangat berbeda.
John
1
@ John: itu semua benar, tapi bukan itu yang diminta OP. OP bertanya, mulai dari vektor yang panjang, untuk menemukan kecocokan pertama dari elemen yang diberikan dalam yang lain. Dan untuk kelengkapannya, saya menambahkan bahwa jika Anda tertarik pada semua indeks, Anda harus menggunakan yang mana (% dalam%). BTW, tidak ada alasan untuk menghapus jawaban Anda. Ini informasi yang valid.
Joris Meys
1
Saya pikir akan sangat membantu untuk menekankan bahwa urutan argumen dalam matchmasalah jika Anda menginginkan indeks kejadian pertama. Sebagai contoh Anda, match(x,c(4,8))berikan hasil yang berbeda, yang pada awalnya tidak terlalu jelas.
apitsch
@goldenoslik Ini membantu jika Anda membaca halaman bantuan match. Semuanya dijelaskan di sana. Tetapi saya menambahkan informasi itu.
Joris Meys
Terima kasih! Solusi ini menyelamatkan hari saya!
Jinhua Wang
26

fungsi Positiondi funprog {base} juga berfungsi . Ini memungkinkan Anda untuk melewati fungsi arbitrer, dan mengembalikan kecocokan pertama atau terakhir.

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

pedroteixeira
sumber
10

Catatan kecil tentang efisiensi metode yang disebutkan di atas:

 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

Jadi, yang terbaik adalah

    which("Feb" == month.abb)[[1]]
Andrii
sumber
Patokan Anda didasarkan pada vektor dengan panjang 12 dan karenanya tidak berarti. Juga dalam contoh Anda which("Feb" == month.abb)mengembalikan 2–mengapa [[1]]?
markus
@markus kode ini yang ("Feb" == month.abb) [[1]] mengembalikan "2", dan kode ini yang (month.abb% dalam% "Feb") juga mengembalikan "2". Juga, tidak jelas mengapa menggunakan vektor tidak berarti
Andrii
1
Ini bukan tentang vektor, tetapi tentang panjangnya. Anda harus membuat vektor dengan panjang yang sesuai dan kemudian melakukan patokan berdasarkan itu. Mengutip dari Ops pertanyaan "Saya tahu bahwa salah satu cara untuk melakukan ini adalah: which(x == v)[[1]] , . Tapi itu tampaknya terlalu tidak efisien"
Markus
-5

R telah membebani ==operator ganda sama dengan metode menemukan indeks jarum di tumpukan jerami vektor. Ini menghasilkan logicalvektor, berisi TRUEnilai untuk setiap pertandingan di tumpukan jerami.

Contoh:

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

Ini berfungsi jika keduanya vektor, dan dapat diperluas untuk menggunakan beberapa vektor juga.

hiten2
sumber
2
The ==Operator sudah disebutkan dalam pertanyaan saya sebagai solusi efisien yang tidak bekerja dengan vektor jarum.
Ryan C. Thompson
"Ini berfungsi jika keduanya vektor" - mungkin, tergantung pada maksud Anda ... tetapi tidak dalam arti yang diinginkan OP.
Frank
30
Saya mendapatkan FALSE FALSE TRUE FALSE TRUEalih-alih indeks dalam contoh ini
Sashko Lykhenko
6
Anda tidak pernah menjalankan ini dalam R. ==mengembalikan vektor logis, bukan indeks. Untuk itu Anda perlu which(), seperti yang saya jelaskan 7 tahun lalu.
Joris Meys