Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating a triangular matrix

Tags:

r

matrix

There must an elegant way to do this but I can't figure out so:

Columns are probabilities from 1 to 0 going right

Rows are probabilities from 0 to 1 going down

This kludgy code produces see the desired result (but I want to do it with a much larger matrix than this):

# 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

Thanks!

like image 923
user1572707 Avatar asked Aug 02 '12 22:08

user1572707


People also ask

What is triangular form matrix?

An atomic (upper or lower) triangular matrix is a special form of unitriangular matrix, where all of the off-diagonal elements are zero, except for the entries in a single column. Such a matrix is also called a Frobenius matrix, a Gauss matrix, or a Gauss transformation matrix.

How do you make a triangular matrix in R?

To create an upper triangular matrix using vector elements, we can first create the matrix with appropriate number of columns and rows then take the transpose of that matrix. After that we will assign the lower triangular matrix elements to 0.

Can a 2x2 matrix be triangular?

In other words, a square matrix is upper triangular if all its entries below the main diagonal are zero. Example of a 2 × 2 upper triangular matrix: A square matrix with elements sij = 0 for j > i is termed lower triangular matrix.


1 Answers

 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

I think this will be much faster than a plyr solution and I happen to think it is easier to comprehend. It basically sets up a test for the entries that are in the lower right hand "triangle" and then divides the results of that "test" matrix bu 10. You can look at the test matrix with this code:

row(mat)+col(mat) -11

Edit: I thought it possible that making the matrix once as sebastian-c illustrated and then doing a single test to do the NA setting might be faster ( with one third the number of calls to row and col) but it appears to be only one third as fast. It looks like the two seq calls take more time than the extra :

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

I did find another solution based on the little known embed function:

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

Although it is 50% faster than the new solution, it is still slower than the original.

like image 143
IRTFM Avatar answered Sep 28 '22 15:09

IRTFM