Re: [R] Summing up diagonals w/o for-loop
Camarda, Carlo Giovanni wrote: > Dear R-users, > > is there any way to sum up the elements of the "diagonals" of a matrix > without using a for-loop? While there is a simple way over rows and > columns, I don't see a straightforward multiplication for the diagonals, > am I too demanding? Or, more likely, I'm lack some algebra trick? Is > there any R-function that can deal with this problem w/o loop? > > Actually I would need to sum up just the upper diagonals. > > Here a simple, but general, example for presenting the problem. > > Thanks in advance for any help, > Carlo Giovanni Camarda > > m<- 7 > n<- 5 > mat<- matrix(1:35, n, m) > ones.r<- rep(1,n) > ones.c<- rep(1,m) > # sum over the rows > sum.r<- mat%*%ones.c > # sum over the cols > sum.c<- t(mat)%*%ones.r > # sum over the diags > sum.d<- numeric(m+n-1) > sum.d[1]<- mat[n,1] > sum.d[m+n-1]<- mat[1,m] > for(i in 2:n){ > sum.d[i]<- sum(diag(mat[(n+1-i):n,1:i])) > } > for(i in 2:(m-1)){ > sum.d[i+n-1]<- sum(diag(mat[,i:m])) > } > If we have 'mat': > mat [,1] [,2] [,3] [,4] [,5] [,6] [,7] [1,]16 11 16 21 26 31 [2,]27 12 17 22 27 32 [3,]38 13 18 23 28 33 [4,]49 14 19 24 29 34 [5,]5 10 15 20 25 30 35 You can use: > rowSums(mat) [1] 112 119 126 133 140 and: > colSums(mat) [1] 15 40 65 90 115 140 165 for your initial steps, rather than the matrix multiplication. See ?colSums for more information. There may be a better way than this, but one approach for the diagonals in the order you want is to split() the matrix into it's constituent diagonals based upon subsetting using the row() and col() values. This yields a list: > split(mat, col(mat) - row(mat)) $`-4` [1] 5 $`-3` [1] 4 10 $`-2` [1] 3 9 15 $`-1` [1] 2 8 14 20 $`0` [1] 1 7 13 19 25 $`1` [1] 6 12 18 24 30 $`2` [1] 11 17 23 29 35 $`3` [1] 16 22 28 34 $`4` [1] 21 27 33 $`5` [1] 26 32 $`6` [1] 31 Then we can use sapply() to sum() over the list elements: > sum.d [1] 5 14 27 44 65 90 115 100 81 58 31 > sapply(split(mat, col(mat) - row(mat)), sum) -4 -3 -2 -1 0 1 2 3 4 5 6 5 14 27 44 65 90 115 100 81 58 31 If you want to sum the diagonals "the other way" replace the '-' in the second argument in split() with a '+'. See ?split, ?sapply, ?row and ?col for more information. HTH, Marc Schwartz __ 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.
Re: [R] Summing up diagonals w/o for-loop
Does this do what you want? > d <- col(mat) - row(mat) > tapply( mat, d, sum ) Hope this helps, -- Gregory (Greg) L. Snow Ph.D. Statistical Data Center Intermountain Healthcare [EMAIL PROTECTED] (801) 408-8111 > -Original Message- > From: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] On Behalf Of Camarda, > Carlo Giovanni > Sent: Tuesday, February 26, 2008 1:32 PM > To: [EMAIL PROTECTED] > Subject: [R] Summing up diagonals w/o for-loop > > Dear R-users, > > is there any way to sum up the elements of the "diagonals" of > a matrix without using a for-loop? While there is a simple > way over rows and columns, I don't see a straightforward > multiplication for the diagonals, am I too demanding? Or, > more likely, I'm lack some algebra trick? Is there any > R-function that can deal with this problem w/o loop? > > Actually I would need to sum up just the upper diagonals. > > Here a simple, but general, example for presenting the problem. > > Thanks in advance for any help, > Carlo Giovanni Camarda > > m <- 7 > n <- 5 > mat <- matrix(1:35, n, m) > ones.r <- rep(1,n) > ones.c <- rep(1,m) > # sum over the rows > sum.r <- mat%*%ones.c > # sum over the cols > sum.c <- t(mat)%*%ones.r > # sum over the diags > sum.d <- numeric(m+n-1) > sum.d[1] <- mat[n,1] > sum.d[m+n-1] <- mat[1,m] > for(i in 2:n){ > sum.d[i] <- sum(diag(mat[(n+1-i):n,1:i])) } for(i in 2:(m-1)){ > sum.d[i+n-1] <- sum(diag(mat[,i:m])) } > > > > -- > This mail has been sent through the MPI for Demographic > ...{{dropped:10}} > > __ > 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.
[R] Summing up diagonals w/o for-loop
Dear R-users, is there any way to sum up the elements of the "diagonals" of a matrix without using a for-loop? While there is a simple way over rows and columns, I don't see a straightforward multiplication for the diagonals, am I too demanding? Or, more likely, I'm lack some algebra trick? Is there any R-function that can deal with this problem w/o loop? Actually I would need to sum up just the upper diagonals. Here a simple, but general, example for presenting the problem. Thanks in advance for any help, Carlo Giovanni Camarda m <- 7 n <- 5 mat <- matrix(1:35, n, m) ones.r <- rep(1,n) ones.c <- rep(1,m) # sum over the rows sum.r <- mat%*%ones.c # sum over the cols sum.c <- t(mat)%*%ones.r # sum over the diags sum.d <- numeric(m+n-1) sum.d[1] <- mat[n,1] sum.d[m+n-1] <- mat[1,m] for(i in 2:n){ sum.d[i] <- sum(diag(mat[(n+1-i):n,1:i])) } for(i in 2:(m-1)){ sum.d[i+n-1] <- sum(diag(mat[,i:m])) } -- This mail has been sent through the MPI for Demographic ...{{dropped:10}} __ 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.