2011-01-19 7 views
5

Soy nuevo en R y estoy tratando de manejar las funciones de la familia de aplicaciones. Específicamente, estoy tratando de escribir una función de orden superior que acepte vectores de 2 caracteres, "host" e "invitado" (que no necesitan ser de la misma longitud) y devuélvame un vector de índice de la misma longitud que "host ", con los elementos resultantes correspondientes a sus índices en invitado (NA si no está allí).¿Cómo puedo vectorizar esta función para devolver un vector de índice?

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

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

Este código devuelve 3 como se esperaba: (? Sapply)

matchIndices(host[1],guest) 

Este es el lazo que me gustaría ser capaz de reemplazar con una función de aplicar sucinta

Este código "funciona" porque produce el resultado a continuación, pero realmente quiero que el resultado sea un vector, y tengo la corazonada de que una de las funciones de aplicar hará el truco. Estoy atascado en cómo escribirlo. Cualquier ayuda sería muy apreciada. Gracias.

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

Respuesta

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

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

Una forma (ineficiente) es sapply sobre el vector host, pasando guest como un argumento (tenga en cuenta que sólo podría simplificar esto a sapply(host, match, guest) pero esto ilustra una forma general de abordar este tipo de cosas):

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

Sin embargo, esto se puede hacer directamente usando match ya que acepta un vector primer argumento:

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

Si quieres un vector llamado como salida,

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

que podría ser envuelto en una función

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

regresar

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

Si realmente desea que los nombres y los partidos se unieron en un vector de cadenas, entonces:

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

que sólo podía hacer 'sapply (host, partido, Habitación) ', no hay necesidad de definir' matchIndices' –

+0

@Prasad Sí, podría, pero lo dejé como si fuera a mostrar cómo aplicar sapply una función de usuario de esta manera. La razón por la que lo dejé fue que todo esto se puede hacer con 'match' directamente, ya que acepta un primer argumento vectorial. Ver mi respuesta actualizada. –

+0

Esto es fabuloso. Muchas gracias. "match (host, guest)" es perfecto. No me di cuenta de que podría ser tan compacto. – user297400

3

si desea que el vector de salida en el formato host;guestNum se usaría do.call, paste, match de la siguiente manera:

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

Como dije, no necesitas 'sapply' en absoluto aquí; 'match' toma un primer argumento vectorial, por lo que podemos simplificarlo a' do.call (pegar, list (host, match (host, guest), sep = ';')) 'pero eso parece un poco exagerado para achieve 'paste (match (host, guest), host, sep ="; ")' o 'paste (host, match (host, guest), sep ="; ")' ¿no es así? –

+0

muy cierto @Gavin, esa es la manera más simple –

+0

maldición, tienes razón. Entonces 'do.call (pegar, list (host, match (host, guest), sep ="; "))' haría –

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" 
Cuestiones relacionadas