Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Paste all possible diagonals of an n*n matrix or dataframe

Tags:

dataframe

r

I'm trying to paste all possible characters that are arranged in any diagonal within an N * N matrix.

For example, consider the following 3 X 3 matrix:

#Create matrix, convert to character dataframe
matrix <- matrix(data=c('s','t','y','a','e','l','f','n','e'),nrow=3,ncol=3)
matrix <- as.data.frame(matrix)
for(i in 1:length(colnames(matrix))){
  matrix[,i] <- as.character(matrix[,i])
}

In the matrix above I need to paste the diagonals: "see","fey", "ees", and "yef". I can find these in the dataframe with the following code:

diag <- paste(matrix[1,1],matrix[2,2],matrix[3,3],sep='')
diag1 <- paste(matrix[1,3],matrix[2,2],matrix[3,1],sep='')
diag2 <- paste(matrix[3,1],matrix[2,2],matrix[1,3],sep='')
diag3 <- paste(matrix[3,3],matrix[2,2],matrix[1,1],sep='')

The problem is that I want to automate this so that it will work on any N x N matrix. (I'm writing a function to find the diagonals in any N X N matrix). Is there an efficient way to do this?

like image 743
schristel Avatar asked May 04 '15 14:05

schristel


People also ask

How do you find diagonal matrices?

A square matrix D = [d ij] n x n will be called a diagonal matrix if d ij = 0, whenever i is not equal to j. There are many types of matrices like the Identity matrix.

What is diagonal matrix of order n?

Any provided square matrix where all the elements have zero value except the principal diagonal elements of a matrix is termed a diagonal matrix. Any matrix in which the number of rows is equivalent to the number of columns, say “n”, is termed as a square matrix of order n.

Are diagonal matrices commutative?

Property 3: Under Multiplication, Diagonal Matrices are commutative, i. e. PQ = QP What is Block Diagonal Matrix? A matrix which is split into blocks is called a block matrix.

How to do diagonal printing of matrix in C++?

Following is the code for diagonal printing. The diagonal printing of a given matrix “matrix[ROW][COL]” always has “ROW + COL – 1” lines in output. C++. /* Get column index of the first element in this line of output.


1 Answers

Oh, that's easy if you use matrix instead of data.frame :) We can choose matrix elements just like we can take vector elements:

matrix[1:3] # First three elements == first column

n <- ncol(matrix)
(1:n-1)*n+1:n
## [1] 1 5 9
(1:n-1)*n+n:1
## [1] 3 5 7

So now we can use this:

matrix[(1:n-1)*n+1:n]
[1] "s" "e" "e"
paste0(matrix[(1:n-1)*n+1:n],collapse="")
[1] "see"

And if you want it backwards, just reverse the vector of indexes using rev function:

paste0(matrix[rev((1:n-1)*n+1:n)],collapse="")
[1] "ees"

Some benchmarks:

rotate <- function(x) t(apply(x, 2, rev))
revMat <- function(mat, dir=0){
    x <- if(bitwAnd(dir,1)) rev(seq(nrow(mat))) else seq(nrow(mat))
    y <- if(bitwAnd(dir,2)) rev(seq(ncol(mat))) else seq(nrow(mat))
    mat[x,y]
}

bartek <- function(matrix){
    n <- ncol(matrix)
    c(paste0(matrix[(1:n-1)*n+1:n],collapse=""), paste0(matrix[rev((1:n-1)*n+1:n)],collapse=""),
      paste0(matrix[(1:n-1)*n+n:1],collapse=""), paste0(matrix[rev((1:n-1)*n+n:1)],collapse=""))
}

Joe <- function(matrix){
    diag0 <- diag(matrix)
    diag1 <- diag(rotate(matrix))
    diag2 <- rev(diag0)
    diag3 <- rev(diag1)
    c(paste(diag0, collapse = ""),paste(diag1, collapse = ""),
      paste(diag2, collapse = ""),paste(diag3, collapse = ""))
}

James <- function(mat){
    sapply(0:3,function(x) paste(diag(revMat(mat,x)),collapse=""))
}

matrix <- matrix(c('s','t','y','a','e','l','f','n','e'), ncol = 3)

microbenchmark(bartek(matrix), Joe(matrix), James(matrix))
Unit: microseconds
           expr     min       lq      mean   median      uq     max neval
 bartek(matrix)  50.273  55.2595  60.78952  59.4390  62.438 134.880   100
    Joe(matrix) 167.431 176.6170 188.46908 182.8260 192.646 337.717   100
  James(matrix) 321.313 334.3350 346.15230 339.7235 348.565 447.115   100


matrix <- matrix(1:10000, ncol=100)
microbenchmark(bartek(matrix), Joe(matrix), James(matrix))
Unit: microseconds
           expr      min       lq      mean   median        uq      max neval
 bartek(matrix)  314.385  326.752  336.1194  331.936  337.9805  423.323   100
    Joe(matrix) 2168.141 2221.477 2460.1002 2257.439 2298.4400 8856.482   100
  James(matrix) 1200.572 1250.354 1407.5943 1276.307 1323.8845 7419.931   100
like image 170
bartektartanus Avatar answered Nov 16 '22 00:11

bartektartanus