2011-11-02 29 views
6

Czy ktoś zna czysty/skuteczny sposób na zastąpienie elementów ukośnych w tablicy, podobnie jak w przypadku macierzy z użyciem diag(x) <- value? Innymi słowy coś takiego:Zastąp elementy przekątnej w tablicy

> 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 

ale bez użycia pętli for (moje tablice są dość duże i manipulacja ta będzie już w pętli).

Wielkie dzięki.

Odpowiedz

6

Spróbuj tego:

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

EDIT:

Pytanie poprosił o schludny/skuteczne, ale, oczywiście, to nie to samo. Jedna linijka jest tutaj kompaktowa i wolna od pętli, ale jeśli szukasz prędkości, to uważam, że pętla w pytaniu jest w rzeczywistości najszybszą ze wszystkich odpowiedzi.

+0

+1 bardzo ładne. Jest szybszy niż mój kod funkcji. –

+0

dobra robota, okrzyki! – gjabel

5

Możesz użyć do tego poniższej funkcji, pod warunkiem, że masz tylko 3 wymiary w swojej macierzy. Można uogólnić do większej liczby wymiarów na podstawie tego kodu, ale jestem zbyt leniwy, aby to zrobić dla ciebie ;-)

`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 
} 

Działa to tak:

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

zauważyć, że w przeciwieństwie do diag() funkcja ta nie może zajmować się macierzami, które nie są kwadratowe. Możesz zajrzeć do kodu źródłowego diag(), aby dowiedzieć się, jak zaadaptować ten kod, aby to zrobić.

+0

niesamowite, działa na leczeniu! – 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 

Jest to napisane z zamiarem, że działa dla wymiarów wyższych niż 3, ale nie przetestowałem go w takim przypadku. Powinno być jednak w porządku.

+0

Nie tworzy macierzy diagonalnej na dims> 2. Tworzy wiele macierzy diagonalnych n x n. – papirrin

Powiązane problemy