2012-08-02 117 views
13

必須有一個優雅的方式來做到這一點,但我想不通這樣:創建一個三角矩陣

列是概率從1到0在朝好的方向發展

行的概率從0到1下降

這個缺憾代碼產生看到期望的結果(但我想用一個比這更大的矩陣做):

# 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 

謝謝!

回答

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

我修正了你的代碼格式,但我也因爲結果看起來不像OP要求的內容而降低了你的評價。 :-( – GSee 2012-08-02 23:44:00

+0

謝謝,GSee。我編輯我的代碼來修復它。 – AGS 2012-08-02 23:55:04

+0

謝謝。downvote撤回。歡迎來到SO! – GSee 2012-08-02 23:57:07

5

一種可能的方式,用我目前最喜歡的庫:

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) 

此給出以下結果:

 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 

的想法是,expand.grid創建所有可能的數據幀單元值。您也可以使用merge。然後,對這些值中的每一個應用函數來計算單元格內容。並且有daply將它變成一個很好的矩陣,包括名字。

編輯:
好的,你想要列相反的順序標記。 ddply將按升序排序。所以,試試這個:

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 

我認爲這將是比plyr解決方案更快,我忽然想到,這是容易理解。它基本上對右下角「三角形」中的條目進行測試,然後將該「測試」矩陣bu10的結果分開。您可以使用此代碼查看測試矩陣:

row(mat)+col(mat) -11 

編輯:我認爲有可能使矩陣一次作爲sebastian-c說明,然後做單個測試來做NA設置可能會更快(有三分之一的呼叫數爲rowcol),但它似乎只是快三分之一。它看起來像兩個序列調用花費更多的時間比多餘的:

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 

我沒有找到基於鮮爲人知embed功能另一種解決方案:

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

雖然它比新的要快50%解決方案,它仍然比原來慢。

+0

(+1)優雅而快速的解決方案。 – chl 2012-08-04 21:17:25

9

稍微不同的解決方案,密切在風格上@迪文的:

與合適的下三角創建一個矩陣(我不認爲四捨五入是絕對必要的,但除此之外,浮點錯誤會使得它看起來很糟糕):

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 

反向的列

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

拆下上部三角形:

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

重新扭轉列:

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 

你可以從那裏改變rownames。

編輯:鑑於有這麼多的解決方案,你可能有興趣看看他們如何基準。使用microbenchmark

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 

@迪文的解決方案似乎是一個相當大的利潤率最快。

+0

做這個基準測試是個好主意! – MvG 2012-08-03 08:06:09