2011-11-23 15 views
6

Tengo el siguiente marco de datos y vector.¿Cómo aplico una función multiparamétrica en R?

> y 
    v1 v2 v3 
1 1 6 43 
2 4 7 5 
3 0 2 32 

> v 
[1] 1 2 3 

quiero aplicar la siguiente función para cada FILA en esa trama de datos tal que v se añade a cada FILA de y:

x <- function(vector1,vector2) { 
    x <- vector1 + vector2 
} 

... con el fin de conseguir Estos resultados:

v1 v2 v3 
1 2 8 46 
2 5 9 8 
3 1 4 35 

mapply aplica la función a COLUMNAS:

> z <- mapply(x, y, MoreArgs=list(vector2=v)) 
> z 
    v1 v2 v3 
[1,] 2 7 44 
[2,] 6 9 7 
[3,] 3 5 35 

he tratado de transposición de la trama de datos de modo que la función se aplicará a las filas y columnas no, pero mapply me da resultados extraños después de la transposición:

> transposed <- t(y) 
> transposed 
    [,1] [,2] [,3] 
v1 1 4 0 
v2 6 7 2 
v3 43 5 32 

> z <- mapply(x, transposed, MoreArgs=list(vector2=v)) 
> z 
    [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] 
[1,] 2 7 44 5 8 6 1 3 33 
[2,] 3 8 45 6 9 7 2 4 34 
[3,] 4 9 46 7 10 8 3 5 35 

... ayuda?

############################ EDIT ################# ########

¡Gracias por todas las respuestas! Estoy aprendiendo toneladas de nuevas funciones R que nunca había visto antes, lo cual es fantástico.

Quiero aclarar un poco mi pregunta anterior. Lo que realmente estoy preguntando es una pregunta mucho más general: cómo aplicar una función multiparamétrica a cada fila en R (en este momento, estoy tentado de concluir que debería usar un ciclo, pero me gustaría averiguar si es posible, solo para referencia futura ...) (También me abstuve a propósito de mostrar el código con el que estoy trabajando, ya que es un poco complicado).

He intentado utilizar la función de barrido como se sugirió, pero me sale el siguiente error:

testsweep <- function(vector, z, n) { 
    testsweep <- z 
} 
> n <- names(Na_exp) 
> n 
[1] "NaCl.10000.2hr.AVG_Signal" "NaCl.10000.4hr.AVG_Signal" 


> t <- head(Li_fcs,n=1) 
> t 
    LiCl.1000.1hr.FoldChange LiCl.2000.1hr.FoldChange LiCl.5000.1hr.FoldChange 
[1,]    -0.05371838    -0.1010928    -0.01939986 
    LiCl.10000.1hr.FoldChange LiCl.1000.2hr.FoldChange 
[1,]     0.1275617    -0.107154 
    LiCl.2000.2hr.FoldChange LiCl.5000.2hr.FoldChange 
[1,]    -0.06760782    -0.09770226 
    LiCl.10000.2hr.FoldChange LiCl.1000.4hr.FoldChange 
[1,]    -0.1124188    -0.06140386 
    LiCl.2000.4hr.FoldChange LiCl.5000.4hr.FoldChange 
[1,]    -0.04323497    -0.04275953 
    LiCl.10000.4hr.FoldChange LiCl.1000.8hr.FoldChange 
[1,]    0.03633496    0.01879461 
    LiCl.2000.8hr.FoldChange LiCl.5000.8hr.FoldChange 
[1,]     0.257977    -0.06357423 
    LiCl.10000.8hr.FoldChange 
[1,]    0.07214176 


> z <- colnames(Li_fcs) 
> z 
[1] "LiCl.1000.1hr.FoldChange" "LiCl.2000.1hr.FoldChange" 
[3] "LiCl.5000.1hr.FoldChange" "LiCl.10000.1hr.FoldChange" 
[5] "LiCl.1000.2hr.FoldChange" "LiCl.2000.2hr.FoldChange" 
[7] "LiCl.5000.2hr.FoldChange" "LiCl.10000.2hr.FoldChange" 
[9] "LiCl.1000.4hr.FoldChange" "LiCl.2000.4hr.FoldChange" 
[11] "LiCl.5000.4hr.FoldChange" "LiCl.10000.4hr.FoldChange" 
[13] "LiCl.1000.8hr.FoldChange" "LiCl.2000.8hr.FoldChange" 
[15] "LiCl.5000.8hr.FoldChange" "LiCl.10000.8hr.FoldChange" 

Pero cuando intento de aplicar barrido ...

> test <- sweep(t, 2, z, n, FUN="testsweep") 
Error in if (check.margin) { : argument is not interpretable as logical 
In addition: Warning message: 
In if (check.margin) { : 
    the condition has length > 1 and only the first element will be used 

Cuando retire el n parámetro de este ejemplo de prueba, el barrido funciona bien. Esto me sugiere que el barrido no se puede usar a menos que todos los parámetros proporcionados para barrido tengan el mismo número de columnas que el vector t, o de longitud 1. Corrígeme si me equivoco ...

Respuesta

0

¿Qué le parece usar? ¿aplicar?

t(apply(y, 1, function(x) x + v)) 
    [,1] [,2] [,3] 
[1,] 2 8 46 
[2,] 5 9 8 
[3,] 1 4 35 

No sé por qué apply devuelve la fila como columnas por lo que debe transponerse.

+0

Definitivamente echaré un vistazo a mdply del paquete plyr. Esto hace exactamente lo que pide. –

+0

Definitivamente echaré un vistazo a mdply del paquete plyr. Esto hace exactamente lo que pide. –

3

Usted está pidiendo a "barrer" V a través de las filas de y con la función "+":

sweep(y, 1, v, FUN="+") 
    v1 v2 v3 
1 2 7 44 
2 6 9 7 
3 3 5 35 
+0

Creo que 'MARGIN' necesita ser 2 porque quiere aplicar' v' a las columnas de 'y'. –

+0

Sí. Yo también pensé eso, pero los dos estábamos equivocados. –

+0

Creo que barrido fue exactamente lo que estaba buscando. El problema es en realidad más complejo que solo agregar el vector. Lo utilicé como ejemplo, ya que era lo más simple que se me vino a la mente. Lo que realmente estaba buscando era una forma de aplicar fácil y rápidamente una función multiparamétrica a cada fila, y eso parece ser lo que hace el barrido. ¡Así que gracias! –

2

no creo que necesita mapply aquí.Sólo tiene que utilizar t() directamente o puede utilizar rep() para hacer el partido de reciclaje como desee:

> set.seed(1) 
> mat <- matrix(sample(1:100, 9, TRUE), ncol = 3) 
> vec <- 1:3 
> 
> mat 
    [,1] [,2] [,3] 
[1,] 27 91 95 
[2,] 38 21 67 
[3,] 58 90 63 
#Approach 1 using t() 
> ans1 <- t(t(mat) + vec) 
#Approach 2 using rep() 
> ans2 <- mat + rep(vec, each = nrow(mat)) 
#Are they the same? 
> identical(ans1, ans2) 
[1] TRUE 
#Hurray! 
> ans1 
    [,1] [,2] [,3] 
[1,] 28 93 98 
[2,] 39 23 70 
[3,] 59 92 66 
+0

+1 para el reciclaje manual a través de 'rep' con' each = '. –

2

Si su problema real es en realidad no es más complicado que esto, usted puede tomar ventaja de las normas de reciclaje de R. Primero debe transponer y, luego agregar, luego transponer el resultado porque las matrices R se almacenan en column-major order.

t(t(y)+v) 
    v1 v2 v3 
1 2 8 46 
2 5 9 8 
3 1 4 35 
0

Definitivamente echaré un vistazo a mdply del paquete plyr. Esto hace exactamente lo que quiere hacer:

mdply(data.frame(mean = 1:5, sd = 1:5), rnorm, n = 2) 
Cuestiones relacionadas