Có một hàm R để tìm chỉ số của một phần tử trong một vectơ không?


324

Trong R, tôi có một phần tử xvà một vectơ v. Tôi muốn tìm chỉ số đầu tiên của một yếu tố trong vđó bằng x. Tôi biết rằng một cách để làm điều này là : which(x == v)[[1]], nhưng điều đó dường như quá kém hiệu quả. Có cách nào trực tiếp hơn để làm điều đó?

Đối với điểm thưởng, có một chức năng hoạt động nếu xlà một vectơ? Đó là, nó sẽ trả về một vectơ chỉ số cho biết vị trí của từng phần tử củax trong v.


Vì R được tối ưu hóa để làm việc với các vectơ, which(x == v)[[1]]nên không hiệu quả lắm. Đó là một ==toán tử so sánh ( ) được áp dụng cho tất cả các phần tử vectơ và một phần tử con trên các chỉ mục ( which). Đó là nó. Không có gì có liên quan, miễn là bạn không chạy 10.000 lần lặp lại cho chức năng này. Các giải pháp khác thích matchPositioncó thể không trả về nhiều dữ liệu như vậy which, nhưng chúng không nhất thiết phải hiệu quả hơn.
BurninLeo

2
Câu hỏi của tôi chỉ định rằng tôi muốn một hàm được vectơ hơn x, và which(x == v)[[1]]không.
Ryan C. Thompson

Câu trả lời:


461

Hàm matchhoạt động trên các vectơ:

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

matchchỉ trả về lần gặp đầu tiên của trận đấu, như bạn yêu cầu. Nó trả về vị trí trong đối số thứ hai của các giá trị trong đối số thứ nhất.

Đối với nhiều kết hợp, %in%là cách để đi:

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%trả về một vectơ logic miễn là đối số thứ nhất, với TRUEgiá trị if đó có thể được tìm thấy trong đối số thứ hai và FALSEngược lại.


Tôi nghĩ rằng một ví dụ với c (2,3,3) và c (1,2,3,4) với cả hai kết quả khớp và% trong% sẽ mang tính hướng dẫn nhiều hơn với ít thay đổi hơn giữa các ví dụ. khớp (c (2,3,3), c (1: 4)) trả về các kết quả khác nhau từ đó (c (2,3,3)% theo% c (1: 4)) mà không cần vectơ đầu tiên dài hơn và như nhiều thay đổi từ ví dụ này sang ví dụ khác Cũng đáng lưu ý rằng họ xử lý các trận đấu không khác nhau rất khác nhau.
John

1
@ John: tất cả đều đúng, nhưng đó không phải là những gì OP yêu cầu. OP đã yêu cầu, bắt đầu từ một vectơ dài, để tìm ra sự kết hợp đầu tiên của các yếu tố được đưa ra trong một yếu tố khác. Và để hoàn thiện, tôi đã thêm rằng nếu bạn quan tâm đến tất cả các chỉ số, bạn sẽ phải sử dụng (% tính theo%). BTW, không có lý do để xóa câu trả lời của bạn. Đó là thông tin hợp lệ.
Joris Meys

1
Tôi nghĩ sẽ hữu ích khi nhấn mạnh rằng thứ tự của các đối số trong matchcác vấn đề nếu bạn muốn chỉ số của lần xuất hiện đầu tiên. Ví dụ của bạn, match(x,c(4,8))đưa ra các kết quả khác nhau, điều này không rõ ràng lúc đầu.
xin lỗi

@goldenoslik Nó giúp nếu bạn đọc trang trợ giúp của match. Tất cả đều được giải thích ở đó. Nhưng tôi đã thêm thông tin đó.
Joris Meys

Cảm ơn! Giải pháp này đã cứu ngày của tôi!
Kim Hoa Vương

26

chức năng Position trong funprog {base} cũng thực hiện công việc. Nó cho phép bạn vượt qua một chức năng tùy ý và trả về kết quả khớp đầu tiên hoặc cuối cùng.

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


10

Một lưu ý nhỏ về hiệu quả của các phương pháp nêu trên:

 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

Vì vậy, tốt nhất là

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

Điểm chuẩn của bạn dựa trên một vectơ dài 12 và do đó không có ý nghĩa. Ngoài ra trong ví dụ của bạn which("Feb" == month.abb)trả về mạng vì 2sao [[1]]?
markus

@markus mã này ("Feb" == tháng.abb) [[1]] trả về "2" và mã này (tháng.abb% trong% "Feb") cũng trả về "2". Ngoài ra, không rõ lý do tại sao sử dụng vectơ không có ý nghĩa
Andrii

1
Nó không phải là về vector, mà là về chiều dài của nó. Bạn nên tạo một vectơ có độ dài phù hợp và sau đó thực hiện một điểm chuẩn dựa trên đó. Trích dẫn từ câu hỏi của OP "Tôi biết rằng một cách để làm điều này là : which(x == v)[[1]] , nhưng điều đó dường như quá kém hiệu quả."
markus

-5

R đã quá tải ==toán tử bằng hai lần với phương pháp tìm chỉ số của kim trong một vectơ hay. Nó mang lại một logicalvectơ, chứa TRUEcác giá trị cho mỗi trận đấu trong haystack.

Thí dụ:

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

Nó hoạt động nếu cả hai đều là vectơ và cũng có thể được mở rộng để sử dụng nhiều vectơ.


2
Các ==nhà điều hành đã được đề cập trong câu hỏi của tôi là một giải pháp hiệu quả mà không làm việc với một vector của kim.
Ryan C. Thompson

"Nó hoạt động nếu cả hai đều là vectơ" - có thể, tùy thuộc vào ý của bạn ... nhưng không phải theo nghĩa mà OP muốn.
Frank

30
Tôi nhận được FALSE FALSE TRUE FALSE TRUEthay vì các chỉ số trong ví dụ này
Sashko Lykhenko

6
Bạn không bao giờ chạy cái này trong R. ==trả về một vectơ logic, không phải chỉ số. Cho rằng bạn cần which(), như tôi đã giải thích 7 năm trước.
Joris Meys
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.