[R] Taking all "complete" diagonals of a matrix

Peter Lomas peter.lomas at ucalgary.ca
Wed Jul 20 03:42:14 CEST 2011


Thanks very much to everyone who replied.  Peter got me on my way with
the use diag() hint, and I came with a less pretty version of Dan's
first option almost at the same time as I got that email.  Seems I
can't avoid one for loop, but one is better than two.

Just as a note, with this code you have to make sure that you are in
fact giving it a matrix, or diag() will error.  I fed it a data frame
unaware, but using as.matrix() works just fine.

diagonals <- function(mat){
 R <- dim(mat)[1]
 C <- dim(mat)[2]
output <- matrix(NA,(R-C+1),C)
for(i in 1:(R-C+1))
   output[i,] <- diag(mat[i:(i+C-1),])
return(output)
}
example <- rbind(rep(1,3),rep(2,3),rep(3,3),rep(4,3),rep(5,3))
diagonals(as.data.frame(example))

Error in output[i, ] <- diag(mat[i:(i + C - 1), ]) :
  number of items to replace is not a multiple of replacement length

Thanks again,
Peter


On Tue, Jul 19, 2011 at 17:34, Nordlund, Dan (DSHS/RDA)
<NordlDJ at dshs.wa.gov> wrote:
>> -----Original Message-----
>> From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-
>> project.org] On Behalf Of Peter Lomas
>> Sent: Tuesday, July 19, 2011 2:16 PM
>> To: r-help at r-project.org
>> Subject: [R] Taking all "complete" diagonals of a matrix
>>
>> Hi R-Help!
>>
>> I am trying to find a nicer way of extracting all the "complete"
>> diagonals
>> of a matrix.  I am working with very large matrices that have many more
>> rows
>> than columns.  I want to be able to extract each of the diagonals that
>> are
>> as long as the number of columns in the matrix.  I have written a
>> rather
>> ugly function that presently does the job.  It illustrates what I am
>> trying
>> to do, but I feel like there must be a cleaner (and faster) way.  Does
>> anybody have any ideas?  Here is what I've done so far:
>>
>> diagonals <- function(mat){
>> output <- matrix(0,(dim(mat)[1]-dim(mat)[2]+1),NCOL(mat))
>> for(i in 1:NROW(output)){
>>    G <- c()
>>    for(j in 1:NCOL(mat)){
>>       G  <-  c(G,mat[(i+j-1),j])
>>       }
>>    output[i,]  <-  G
>>   }
>>  return(output)
>> }
>>
>> example <- rbind(rep(1,3),rep(2,3),rep(3,3),rep(4,3),rep(5,3))
>>
>> example
>>      [,1] [,2] [,3]
>> [1,]    1    1    1
>> [2,]    2    2    2
>> [3,]    3    3    3
>> [4,]    4    4    4
>> [5,]    5    5    5
>>
>>  diagonals(example)
>>      [,1] [,2] [,3]
>> [1,]    1    2    3
>> [2,]    2    3    4
>> [3,]    3    4    5
>>
>> Many thanks,
>> Peter
>>
>
> Peter,
>
> Here are two possibilities.  I leave it up to you to determine whether they are cleaner or faster.
>
> diagonals1 <- function(mat){
>  #setup
>  R <- dim(mat)[1]
>  C <- dim(mat)[2]
>  output <- matrix(0,(R-C+1),C)
>  #get diagonals
>  for(i in 1:(R-C+1)) output[i,] <- diag(mat[i:(i+C-1),])
>  return(output)
> }
>
> diagonals2 <- function(mat){
>  #setup
>  R <- dim(mat)[1]
>  C <- dim(mat)[2]
>  output <- matrix(0,(R-C+1),C)
>  #get diagonals
>  for(i in 1:(R-C+1)) output[,i] <- mat[i:(i+C-1),i]
>  return(output)
> }
>
>
> Hope this is helpful,
>
> Dan
>
> Daniel J. Nordlund
> Washington State Department of Social and Health Services
> Planning, Performance, and Accountability
> Research and Data Analysis Division
> Olympia, WA 98504-5204
>
> ______________________________________________
> R-help at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> and provide commented, minimal, self-contained, reproducible code.
>
>



More information about the R-help mailing list