2011-11-02 6 views
6

Est-ce que quelqu'un connaît un moyen propre/efficace de remplacer les éléments diagonaux dans le tableau, similaire à l'utilisation de diag(x) <- value pour une matrice? Autrement dit quelque chose comme ceci:Remplacer les éléments diagonaux dans un tableau

> m<-array(1:27,c(3,3,3)) 
> for(k in 1:3){ 
+ diag(m[,,k])<-5 
+ } 
> m 
, , 1 

    [,1] [,2] [,3] 
[1,] 5 4 7 
[2,] 2 5 8 
[3,] 3 6 5 

, , 2 

[,1] [,2] [,3] 
[1,] 5 13 16 
[2,] 11 5 17 
[3,] 12 15 5 

, , 3 

    [,1] [,2] [,3] 
[1,] 5 22 25 
[2,] 20 5 26 
[3,] 21 24 5 

mais sans l'utilisation d'une boucle for (mes tableaux sont assez grandes et cette manipulation seront déjà dans une boucle).

Merci beaucoup.

Répondre

6

Essayez ceci:

with(expand.grid(a = 1:3, b = 1:3), replace(m, cbind(a, a, b), 5)) 

EDIT:

La question posée pour mais propre/efficace, bien sûr, ce ne sont pas la même chose. Le seul revêtement ici est compact et sans boucle, mais si vous cherchez la vitesse, je pense que vous trouverez que la boucle dans la question est en fait la plus rapide de toutes les réponses.

+0

+1 très agréable. C'est plus rapide que mon code de fonction. –

+0

beau travail, bravo! – gjabel

5

Vous pouvez utiliser la fonction suivante à condition que vous n'ayez que 3 dimensions dans votre baie. Vous pouvez généraliser à plusieurs dimensions en fonction de ce code, mais je suis trop paresseux pour le faire pour vous ;-)

`arraydiag<-` <- function(x,value){ 
    dims <- dim(x) 
    id <- seq_len(dims[1]) + 
     dims[2]*(seq_len(dims[2])-1) 
    id <- outer(id,(seq_len(dims[3])-1)*prod(dims[1:2]),`+`) 
    x[id] <- value 
    dim(x) <- dims 
    x 
} 

Cela fonctionne comme:

m<-array(1:36,c(3,3,4)) 
arraydiag(m)<-NA 
m 

Notez que, contrairement au diag(), cette fonction ne peut pas gérer les matrices qui ne sont pas carrées. Vous pouvez regarder le code source de diag() pour savoir comment adapter ce code dans l'ordre.

+0

génial, fonctionne un régal! – gjabel

3
diagArr <- 
function (dim) 
{ 
    n <- dim[2] 
    if(dim[1] != n) stop("expecting first two dimensions to be equal") 
    d <- seq(1, n*n, by=n+1) 
    as.vector(outer(d, seq(0, by=n*n, length=prod(dim[-1:-2])), "+")) 
} 

m[diagArr(dim(m))] <- 5 

Ceci est écrit dans l'intention que cela fonctionne pour les dimensions supérieures à 3, mais je ne l'ai pas testé dans ce cas. Cela devrait bien se passer.

+0

Il ne crée pas de matrice diagonale sur les dims> 2. Il crée plusieurs matrices diagonales n x n. – papirrin

Questions connexes