2010-08-24 26 views
6

J'utilise R, et j'ai deux data.frames, A et B. Ils ont tous les deux 6 rangées, mais A a 25000 colonnes (gènes), et B a 30 colonnes. Je voudrais appliquer une fonction avec deux arguments f(x,y) où est chaque colonne de A et y est chaque colonne de B. Jusqu'à présent, il ressemble à ceci:Appliquer sur deux trames de données

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

Je soulève deux problèmes: de ma programmation Python j'associe le suivi des compteurs comme celui-ci comme crufty, et de ma programmation R Je suis nerveux pour les boucles. Cependant, je ne peux pas vraiment voir comment appliquer apply (ou même si je devrais appliquer apply) à ce problème et j'espérais que quelqu'un pourrait m'éclairer. J'ai besoin de traiter f() comme atomique (c'est en fait cor.test()) pour l'instant.

+0

Selon 'f', cela semble similaire au produit interne. Je sais avec le produit externe, vous pouvez spécifier une fonction à utiliser, mais je ne sais pas comment le faire pour le produit intérieur. – James

+1

J'hésite à suggérer quoi que ce soit comme je suis un tout nouvel utilisateur de R, mais j'ai eu beaucoup de succès en utilisant le paquetage plyr pour la manipulation de données. http://had.co.nz/plyr/ – dnagirl

Répondre

6

Puisque vous utilisez des trames de données, il pourrait être plus rapide d'utiliser lapply ou sapply pour le faire (spécialement compte tenu de la portée de vos trames de données). Par exemple,

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

L'imbrication des travaux s'applique, mais pas la syntaxe la plus simple.

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

Donc le premier argument de 'function()' toujours celui référencé dans le apply, alors vous fournissez le second comme argument supplémentaire. Merci! La syntaxe est OK dans la notation de la question: 'appliquer (A, 2, fonction (a, B) {appliquer (B, 2, f, a)}, B)' mais encore, beaucoup plus difficile lire plutôt qu'écrire? Je pense que je devrais écrire un wrapper si f (a, b) n'était pas symétrique ... –

2

Certaines données

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

L'astuce: souvenez-vous des colonnes avec expand.grid

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

Maintenant, nous avons seulement besoin 1 appel à apply.

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