2011-01-19 32 views
5

Tôi mới sử dụng R và đang cố gắng xử lý họ ứng dụng chức năng. Cụ thể, tôi đang cố viết hàm bậc cao hơn sẽ chấp nhận 2 vectơ ký tự, "máy chủ" và "khách" (không cần phải có cùng độ dài) và trả lại cho tôi một vector chỉ mục có cùng độ dài với "máy chủ lưu trữ ", với các yếu tố kết quả tương ứng với chỉ số của họ trong khách (NA nếu không có).Làm thế nào tôi có thể vector hóa chức năng này để trả về một vector chỉ mục?

host <- c("A","B","C","D") 
guest <- c("D","C","A","F") 

matchIndices <- function(x,y) 
{ 
    return(match(x,y)) 
} 

Mã này trả về 3 như mong đợi: (? Sapply)

matchIndices(host[1],guest) 

Đây là vòng lặp Tôi muốn để có thể thay thế với một áp dụng chức năng gọn gàng

Mã này "hoạt động" ở chỗ nó tạo ra kết quả dưới đây, nhưng tôi thực sự muốn kết quả là một véc-tơ, và tôi có linh cảm rằng một trong các hàm áp dụng sẽ thực hiện thủ thuật. Tôi chỉ bị mắc kẹt về cách viết nó. Bất kỳ trợ giúp sẽ được đánh giá cao nhất. Cảm ơn.

3; A; NA; B; 2; C; 1; D;

Trả lời

8
host <- c("A","B","C","D") 
guest <- c("D","C","A","F") 

matchIndices <- function(x,y) { 
    return(match(x,y)) 
} 

One (không hiệu quả) là cách để sapply qua host vector, đi qua trong guest như một đối số (lưu ý bạn chỉ có thể đơn giản hóa này để sapply(host, match, guest) nhưng điều này minh họa một cách tổng quát tiếp cận các loại điều này):

> sapply(host, matchIndices, guest) 
A B C D 
3 NA 2 1 

Tuy nhiên, điều này có thể được thực hiện trực tiếp sử dụng match vì nó chấp nhận một vector số đầu tiên:

> match(host, guest) 
[1] 3 NA 2 1 

Nếu bạn muốn có một vector có tên là đầu ra,

> matched <- match(host, guest) 
> names(matched) <- host 
> matched 
A B C D 
3 NA 2 1 

có thể được gói gọn trong một hàm

matchIndices2 <- function(x, y) { 
    matched <- match(x, y) 
    names(matched) <- x 
    return(matched) 
} 

trở

> matchIndices2(host, guest) 
A B C D 
3 NA 2 1 

Nếu bạn thực sự muốn tên và các kết quả khớp với nhau thành một vectơ của các chuỗi, sau đó:

> paste(match(host, guest), host, sep = ";") 
[1] "3;A" "NA;B" "2;C" "1;D" 
+1

bạn chỉ có thể làm 'sapply (host, phù hợp, khách) ', không cần phải xác định' matchIndices' –

+0

@Prasad Có, bạn có thể nhưng tôi để lại điều này giống như nó là để cho thấy làm thế nào để sapply một chức năng người dùng trong thời trang này. Lý do tôi để nó như thế này tất cả có thể được thực hiện với 'match' trực tiếp vì nó chấp nhận một đối số đầu tiên vector. Xem câu trả lời cập nhật của tôi. –

+0

Điều này thật tuyệt vời. Cảm ơn nhiều. "match (host, guest)" là hoàn hảo. Tôi không nhận ra rằng nó có thể nhỏ gọn. – user297400

3

nếu bạn muốn vector đầu ra theo định dạng host;guestNum bạn sẽ sử dụng do.call, paste, match như sau:

> do.call(paste, list(host, sapply(host, match, guest), sep = ';'))                      
[1] "A;3" "B;NA" "C;2" "D;1" 
+2

Như tôi đã nói, bạn không cần phải "lưỡng lự" ở đây; 'match' lấy đối số đầu tiên của vector, vì vậy chúng ta có thể đơn giản hóa điều này thành' do.call (dán, danh sách (máy chủ, kết hợp (máy chủ, khách), sep = ';')) 'nhưng có vẻ như một chút quá mức cần thiết để đạt được 'dán (match (host, guest), host, sep ="; ")' hoặc 'paste (host, match (host, guest), sep ="; ")' hiện nó không? –

+0

@Gavin rất đúng, đó là cách đơn giản nhất –

+0

darn, bạn nói đúng. Vì vậy 'do.call (paste, list (host, match (host, guest), sep ="; "))' sẽ làm –

2
sapply(host , function(x) which(guest==x)) 
$A 
[1] 3 

$B 
integer(0) 

$C 
[1] 2 

$D 
[1] 1 


unlist(sapply(host , function(x) which(guest==x))) 

    A C D 
    3 2 1 

paste(host, sapply(host , function(x) which(guest==x)), sep=":", collapse=" ") 
[1] "A:3 B:integer(0) C:2 D:1" 
Các vấn đề liên quan