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) <nord...@dshs.wa.gov> wrote: >> -----Original Message----- >> From: r-help-boun...@r-project.org [mailto:r-help-bounces@r- >> project.org] On Behalf Of Peter Lomas >> Sent: Tuesday, July 19, 2011 2:16 PM >> To: r-help@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@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. > > ______________________________________________ R-help@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.