2010-07-07 9 views
3

Je suis coincé avec une simple boucle qui prend plus d'une heure à courir, et j'ai besoin d'aide pour l'accélérer.Valeur de retour de la colonne indiquée dans la même ligne

Fondamentalement, j'ai une matrice avec 31 colonnes et 400 000 lignes. Les 30 premières colonnes ont des valeurs, et la 31ème colonne a un numéro de colonne. Je dois, par ligne, récupérer la valeur dans la colonne indiquée par la 31ème colonne.

Exemple ligne: [26,354,72,5987 .., 461,3] (ce qui signifie que la valeur dans la colonne 3 est recherchée (72))

La boucle trop lente se présente comme suit:

a <- rep(0,nrow(data)) #To pre-allocate memory 
for (i in 1:nrow(data)) { 
    a[i] <- data[i,data[i,31]] 
} 

Je pense que cela fonctionnerait:

a <- data[,data[,31]] 

... mais il se traduit par "erreur: ne peut pas attribuer vecteur de taille 2.8 Mb".

Je crains que ce soit une question très simple, donc j'ai passé des heures à essayer de comprendre appliquer, lapply, remodeler et plus, mais de toute façon je ne peux pas avoir une emprise sur le concept de vectorisation dans R.

La matrice a en fait encore plus de colonnes qui vont aussi dans le paramètre a, c'est pourquoi je ne veux pas reconstruire la matrice, ou la diviser.

Votre soutien est grandement apprécié!

Chris

+1

Êtes-vous sûr qu'il y a suffisamment de RAM libre? – mbq

+1

s'appliquent et les amis n'ont rien à voir avec la vectorisation. – Shane

+0

Votre exemple créerait une autre matrice, de la même taille que celle d'origine.On dirait que vous manquez de RAM dans votre espace de travail - un vecteur numérique de longueur 400000 prend 3.1 Mb, et la matrice devrait prendre 94.6 Mb. – James

Répondre

2
t(data[,1:30])[30*(0:399999)+data[,31]] 

Cela fonctionne parce que vous pouvez faire référence à la fois au format matricies de tableau, et le format vectoriel (un 400000 * 31 vecteur à long dans ce cas) le comptage en colonne d'abord. Pour compter le rang, vous utilisez la transposition.

0

La notation par un singe-index pour la matrice peut utiliser moins de mémoire. Cela implique de faire quelque chose comme:

i <- nrow(data)*(data[,31]-1) + 1:nrow(data) 
a <- data[i] 

est Ci-dessous un exemple de notation unique indice pour les matrices dans R. Dans cet exemple, l'indice du maximum par ligne est ajoutée comme la dernière colonne d'une matrice aléatoire . Cette dernière colonne est ensuite utilisée pour sélectionner les maxima par ligne via la notation à index unique.

## create a random (10 x 5) matrix                               
M <- matrix(rpois(50,50),10,5) 
## use the last column to index the maximum value of the first 5                        
## columns                                     
MM <- cbind(M,apply(M,1,which.max)) 
##    column ID   row ID                              
i <- nrow(MM)*(MM[,ncol(MM)]-1) + 1:nrow(MM) 
all(MM[i] == apply(M,1,max)) 

L'utilisation d'un index matrix est une alternative qui va probablement utiliser plus de mémoire, mais est légèrement plus claire:

ii <- cbind(1:nrow(MM),MM[,ncol(MM)]) 
all(MM[ii] == apply(M,1,max)) 
0

Essayez de changer le code pour une colonne à la fois:

M <- matrix(rpois(30*400000,50),400000,30) 
MM <- cbind(M,apply(M,1,which.max)) 
a <- rep(0,nrow(MM)) 
for (i in 1:(ncol(MM)-1)) { 
    a[MM[, ncol(MM)] == i] <- MM[MM[, ncol(MM)] == i, i] 
} 

Ceci définit tous les éléments dans un avec les valeurs de la colonne i si le dernier col umn a la valeur i. Il a fallu plus de temps pour construire la matrice que pour calculer le vecteur un.