2012-08-02 13 views
13

Musi elegancki sposób to zrobić, ale nie mogę dowiedzieć się, więc:tworząc trójkątny matrycę

Kolumny są prawdopodobieństwa od 1 do 0 idzie dobrze

Wiersze są prawdopodobieństw od 0 do 1 schodząc

Ten kludgy kod produkuje zobaczyć pożądany rezultat (ale chcę zrobić to z dużo większej matrycy niż w tym):

# Vector entries are rowname - colname, if >= 0 
# 
rb0 <- c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA, 0) 
rb1 <- c(NA,NA,NA,NA,NA,NA,NA,NA,NA, 0,.1) 
rb2 <- c(NA,NA,NA,NA,NA,NA,NA,NA, 0,.1,.2) 
rb3 <- c(NA,NA,NA,NA,NA,NA,NA, 0,.1,.2,.3) 
rb4 <- c(NA,NA,NA,NA,NA,NA, 0,.1,.2,.3,.4) 
rb5 <- c(NA,NA,NA,NA,NA, 0,.1,.2,.3,.4,.5) 
rb6 <- c(NA,NA,NA,NA, 0,.1,.2,.3,.4,.5,.6) 
rb7 <- c(NA,NA,NA, 0,.1,.2,.3,.4,.5,.6,.7) 
rb8 <- c(NA,NA, 0,.1,.2,.3,.4,.5,.6,.7,.8) 
rb9 <- c(NA, 0,.1,.2,.3,.4,.5,.6,.7,.8,.9) 
rb10 <- c(0,.1,.2,.3,.4,.5,.6,.7,.8,.9,1) 
indbias <- rbind(rb0,rb1,rb2,rb3,rb4,rb5,rb6,rb7,rb8,rb9,rb10) 
colnames(indbias) <- seq(1,0,by=-.1) 
rownames(indbias) <- seq(0,1,by=.1) 
indbias 

Dzięki!

Odpowiedz

3
require(matlab) 
x=matrix(seq(0,1,.1),1) 
X=x[rep(1,c(11)),] 
X[upper.tri(X)]=NA 
X=t(X) 
for(a in 1:11){ 
    X[1:a,a]=rev(X[1:a,a]) 
} 
X=flipud(X) 
colnames(X) <- seq(1,0,by=-.1) 
rownames(X) <- seq(0,1,by=.1) 
+0

Naprawiłem formatowanie kodu, ale również przeszedłem na dół, ponieważ wynik nie wygląda dokładnie tak, jak żądał OP. :-( – GSee

+0

Dzięki, GSee. Poprawiłem mój kod, – AGS

+0

dziękuję ... downvote wycofane Witaj w SO! – GSee

5

Jednym z możliwych sposobów, używając mojego obecnego ulubionego Biblioteka:

library(plyr) 
daply(expand.grid(x=seq(1,0,-.1), y=seq(0,1,.1)), 
     .(y, x), with, 
     if (x+y >= 1) x+y-1 else NA) 

To daje następujący wynik:

 x 
y  0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 
    0 NA NA NA NA NA NA NA NA NA NA 0.0 
    0.1 NA NA NA NA NA NA NA NA NA 0.0 0.1 
    0.2 NA NA NA NA NA NA NA NA 0.0 0.1 0.2 
    0.3 NA NA NA NA NA NA NA 0.0 0.1 0.2 0.3 
    0.4 NA NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 
    0.5 NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 
    0.6 NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 
    0.7 NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 
    0.8 NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 
    0.9 NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 
    1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 

Chodzi o to, że expand.grid tworzy ramkę danych możliwe wartości komórek. Równie dobrze można do tego użyć merge. Następnie stosujesz funkcję do każdej z tych wartości, aby obliczyć zawartość komórki. I zamień go na ładną matrycę, włącznie z imionami.

EDIT:
OK, chciałeś kolumny oznaczone w odwrotnej kolejności. ddply posortuje je rosnąco. Więc spróbuj tego:

daply(expand.grid(x=seq(0,1,.1), y=seq(0,1,.1)), 
     .(y, x), with, 
     if (y-x >= 0) y-x else NA)[,11:1] 
 x 
y  1 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0 
    0 NA NA NA NA NA NA NA NA NA NA 0.0 
    0.1 NA NA NA NA NA NA NA NA NA 0.0 0.1 
    0.2 NA NA NA NA NA NA NA NA 0.0 0.1 0.2 
    0.3 NA NA NA NA NA NA NA 0.0 0.1 0.2 0.3 
    0.4 NA NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 
    0.5 NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 
    0.6 NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 
    0.7 NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 
    0.8 NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 
    0.9 NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 
    1 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 
18
mat <- matrix(NA, 10,10) 
mat[row(mat)+col(mat) >=11] <- (row(mat)+col(mat) -11)[row(mat)+col(mat)>=11]/10 
mat 
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
[1,] NA NA NA NA NA NA NA NA NA 0.0 
[2,] NA NA NA NA NA NA NA NA 0.0 0.1 
[3,] NA NA NA NA NA NA NA 0.0 0.1 0.2 
[4,] NA NA NA NA NA NA 0.0 0.1 0.2 0.3 
[5,] NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 
[6,] NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 
[7,] NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 
[8,] NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 
[9,] NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 
[10,] 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 

myślę, że to będzie znacznie szybciej niż rozwiązanie plyr i zdarza mi się, że to jest łatwiejsze do zrozumienia. Zasadniczo ustawia test dla wpisów, które znajdują się w prawym dolnym rogu "trójkąt", a następnie dzieli wyniki tej "testowej" macie bu 10. Możesz spojrzeć na matrycę testową z tym kodem:

row(mat)+col(mat) -11 

Edycja: Pomyślałem, że możliwe, że tworzenie macierzy raz jako sebastian-c zilustrowane, a następnie wykonanie pojedynczego testu w celu ustawienia NA może być szybsze (z jedną trzecią liczbą wywołań na row i col), ale wydaje się, że jest tylko jedna trzecia tak szybko. Wygląda na to, że dwie rozmowy seq zająć więcej czasu niż dodatkowa:

mat <- round(outer(seq(-0.5, 0.5, 0.1), seq(-0.5, 0.5, 0.1), `+`), 1) 
is.na(mat) <- row(mat)+col(mat) <= 11 
mat 

znalazłem inne rozwiązanie oparte na mało znanego embed funkcję:

mat <- embed(seq(-1,1, by=0.1), 11)[,11:1] 
is.na(mat) <- row(mat)+col(mat) <= 11 

Chociaż jest to 50% szybciej niż nowa rozwiązanie, wciąż jest wolniejsze niż oryginał.

+0

(+1) Eleganckie i szybkie rozwiązanie – chl

9

Nieco inne rozwiązanie, w pobliżu w stylu @ Dwin użytkownika:

utworzyć macierz z odpowiednim dolnego trójkąta (nie sądzę zaokrąglanie jest to bezwzględnie konieczne, ale poza tym pływające błąd punkt sprawia, że ​​wygląda okropnie):

mat <- round(outer(seq(-0.5, 0.5, 0.1), seq(-0.5, 0.5, 0.1), `+`), 1) 
mat 

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] 
[1,] -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 
[2,] -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 
[3,] -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 
[4,] -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 
[5,] -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 
[6,] -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 
[7,] -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 
[8,] -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 
[9,] -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 
[10,] -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 
[11,] 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 

Rewers kolumn

mat <- mat[,rev(seq.int(ncol(mat)))] 

zdjąć górną trójkąta:

mat[upper.tri(mat)] <- NA 

Ponownie odwrócić kolumny:

mat <- mat[,rev(seq_len(ncol(mat)))] 
mat 

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] 
[1,] NA NA NA NA NA NA NA NA NA NA 0.0 
[2,] NA NA NA NA NA NA NA NA NA 0.0 0.1 
[3,] NA NA NA NA NA NA NA NA 0.0 0.1 0.2 
[4,] NA NA NA NA NA NA NA 0.0 0.1 0.2 0.3 
[5,] NA NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 
[6,] NA NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 
[7,] NA NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 
[8,] NA NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 
[9,] NA NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 
[10,] NA 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 
[11,] 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 

Można zmienić rownames stamtąd.

EDYCJA: Biorąc pod uwagę, że istnieje tak wiele rozwiązań, być może zainteresuje Cię sposób ich porównywania. Korzystanie microbenchmark: pojawia

Unit: microseconds 
    expr  min   lq  median   uq  max 
1 AGS() 682.491 738.9370 838.0955 892.8815 4518.740 
2 DW() 23.244 27.1680 31.3930 34.8650 70.937 
3 MvG() 15469.664 15920.4820 17352.3215 17827.4380 18989.270 
4 SC() 118.629 131.4575 144.1360 157.7190 631.779 

@ rozwiązania Dwin by być najszybszym przez dość margines.

+0

Ten benchmark to dobry pomysł! – MvG