2011-01-19 3 views
5

Я новичок в R и пытаюсь получить дескриптор применимого семейства функций. В частности, я пытаюсь написать функцию более высокого порядка, которая будет принимать 2 символьных вектора, «хост» и «гость» (которые не должны иметь одинаковую длину) и вернуть мне индексный указатель той же длины, что и «хост» », а результирующие элементы соответствуют их индексам в гостях (NA, если нет).Как я могу векторизовать эту функцию для возврата вектора индекса?

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

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

Этот код возвращает 3, как и ожидалось: (? Sapply)

matchIndices(host[1],guest) 

Это цикл я хотел бы, чтобы иметь возможность заменить с емким функции применяются

Этот код «работает» в том, что он выводит результат ниже, но я действительно хочу, чтобы результат был вектором, и у меня есть догадка, что одна из прикладных функций выполнит трюк. Я просто зациклился на том, как писать. Любая помощь будет оценена по достоинству. Благодарю.

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

ответ

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

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

Один (неэффективный) способ заключается в sapply над host вектором, переходящая в guest в качестве аргумента (обратите внимание, вы могли бы просто упростить это sapply(host, match, guest) но это иллюстрирует общий путь приближения такого рода вещи):

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

Однако, это может быть сделано непосредственно используя match как он принимает вектор первый аргумент:

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

Если вы хотите именованный вектор в качестве вывода,

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

, которые могут быть обернуты в функцию

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

возвращение

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

Если вы действительно хотят имена и совпадения склеиваются в вектор строк, затем:

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

вы можете просто сделать 'sapply (хост, матч, гость) ', не нужно определять' matchIndices' –

+0

@Prasad Да, вы могли бы, но я оставил его так, как будто он показывал, как использовать функцию пользователя таким образом. Причина, по которой я ее оставил, - это все можно сделать с помощью 'match' непосредственно, поскольку он принимает векторный первый аргумент. См. Мой обновленный ответ. –

+0

Это потрясающе. Большое спасибо. «match (host, guest)» идеально. Я не понимал, что это может быть так компактно. – user297400

3

если вы хотите выходной вектор в формате host;guestNum вы будете использовать do.call, paste, match следующим образом:

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

Как я уже сказал, вам вообще не нужно 'sapply'; 'match' принимает векторный первый аргумент, поэтому мы можем упростить это до' do.call (paste, list (host, match (host, guest), sep = ';')) ', но это кажется немного переборщиком получить 'paste (match (host, guest), host, sep ="; ")' или 'paste (host, match (host, guest), sep ="; ")' does not? –

+0

очень верно @Gavin, это самый простой способ –

+0

чертовски, вы правы. Итак, 'do.call (вставить, список (host, match (host, guest), sep ="; "))' будет делать –

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" 
Смежные вопросы