2010-08-24 10 views
6

Estoy usando R, y tengo dos data.frames, A y B. Ambos tienen 6 filas, pero A tiene 25000 columnas (genes) y B tiene 30 columnas. Me gustaría aplicar una función con dos argumentos f(x,y) donde x es cada columna de A y y es cada columna de B. Hasta ahora se ve así:Aplicar sobre dos marcos de datos

i = 1 
for (x in A){ 
    j = 1 
    for (y in B){ 
     out[i,j] <- f(x,y) 
     j = j + 1 
    } 
    i = i + 1 
} 

Tengo dos problemas con esto: desde mi programación Python asocio hacer el seguimiento de los contadores como éste, ya enrevesada, y desde mi programación R Estoy nervioso de los bucles. Sin embargo, no puedo ver cómo aplicar apply (o incluso si debo aplicar apply) a este problema y esperaba que alguien me ilumine. Necesito tratar f() como atómico (en realidad es cor.test()) por el momento.

+0

Dependiendo de 'f', esto suena similar al producto interno. Sé con el producto externo que puede especificar una función para usar, pero no sé cómo hacerlo para el producto interno. – James

+1

No me gusta sugerir nada ya que soy un nuevo usuario de R, pero he tenido mucho éxito utilizando el paquete plyr para la manipulación de datos. http://had.co.nz/plyr/ – dnagirl

Respuesta

6

dado que está utilizando tramas de datos, que podría ser más rápido usar lapply o sapply para hacer esto (especialmente dado el alcance de sus tramas de datos). Por ejemplo,

x <- data.frame(col1=c(1,2,3,4), col2=c(5,6,7,8), col3=c(9,10,11,12)) 
y <- data.frame(col1=c(1,2,3,4), col2=c(5,6,7,8)) 
bl <- lapply(x, function(u){ 
    lapply(y, function(v){ 
     f(u,v) # Function with column from x and column from y as inputs 
    }) 
}) 
out = matrix(unlist(bl), ncol=ncol(y), byrow=T) 
1

Sin embargo, anidar las obras aplicadas no es la sintaxis más fácil.

x<-data.frame(col1=c(1,2,3,4), col2=c(5,6,7,8), col3=c(9,10,11,12)) 
y<-data.frame(col1=c(1,2,3,4), col2=c(5,6,7,8)) 

z<-apply(x,2,function(col,df2) 
      { 
       apply(df2,2,function(col2,col1) 
          { 
           col2+col1 
          },col) 
      },y) 

z 
col1 col2 col3 
[1,] 2 6 10 
[2,] 4 8 12 
[3,] 6 10 14 
[4,] 8 12 16 
[5,] 6 10 14 
[6,] 8 12 16 
[7,] 10 14 18 
[8,] 12 16 20 
+0

Por lo tanto, el primer argumento de 'function()' siempre es el que se hace referencia en la aplicación, luego se proporciona el segundo como argumento adicional. ¡Gracias! La sintaxis está bien en la notación de la pregunta: 'aplicar (A, 2, función (a, B) {aplicar (B, 2, f, a)}, B)' pero aún así, mucho más difícil para leer que para escribir? Creo que tendría que escribir un contenedor si f (a, b) no era simétrico ... –

2

Algunos datos

nrows <- 6 
A <- data.frame(a = runif(nrows), b = runif(nrows), c = runif(nrows)) 
B <- data.frame(z = rnorm(nrows), y = rnorm(nrows)) 

El truco: recuerde columnas con expand.grid

counter <- expand.grid(seq_along(A), seq_along(B)) 
f <- function(x) 
{ 
    cor.test(A[, x["Var1"]], B[, x["Var2"]])$estimate 
} 

Ahora sólo tenemos 1 llamada a apply.

stats <- apply(counter, 1, f) 
names(stats) <- paste(names(A)[counter$Var1], names(B)[counter$Var2], sep = ",") 
stats 
Cuestiones relacionadas