rowsum for matrix over specified number of columns

2019-04-10 03:32发布

问题:

I'm trying to get the sum of columns in a matrix in R for a certain row. However, I don't want the whole row to be summed but only a specified number of columns i.e. in this case all column above the diagonal. I have tried sum and rowSums function but they are either giving me strange results or an error message. To illustrate, please see example code for an 8x8 matrix below. For the first row I need the sum of the row except item [1,1], for second row the sum except items [2,1] and [2,2] etc.

m1 <- matrix(c(0.2834803,0.6398198,0.0766999,0.0000000,0.0000000,0.0000000,0.0000000,0.0000000,
               0.0000000,0.1101746,0.6354086,0.2544168,0.0000000,0.0000000,0.0000000,0.0000000,
               0.0000000,0.0000000,0.0548145,0.9451855,0.0000000,0.0000000,0.0000000,0.0000000,
               0.0000000,0.0000000,0.0000000,0.3614786,0.6385214,0.0000000,0.0000000,0.0000000,
               0.0000000,0.0000000,0.0000000,0.0000000,0.5594658,0.4405342,0.0000000,0.0000000,
               0.0000000,0.0000000,0.0000000,0.0000000,0.0000000,0.7490395,0.2509605,0.0000000,
               0.0000000,0.0000000,0.0000000,0.0000000,0.0000000,0.0000000,0.5834363,0.4165637,
          0.0000000,0.0000000,0.0000000,0.0000000,0.0000000,0.0000000,0.0000000,1.0000000),
             8, 8, byrow = TRUE, 
             dimnames = list(c("iAAA", "iAA", "iA", "iBBB", "iBB", "iB", "iCCC", "iD"),
                  c("iAAA_p", "iAA_p", "iA_p", "iBBB_p", "iBB_p", "iB_p", "iCCC_p", "iD_p")))

I have tried the following:

rowSums(m1[1, 2:8]) --> Error in rowSums(m1[1, 2:8]) : 
  'x' must be an array of at least two dimensions

Alternatively:

sum(m1[1,2]:m1[1,8]) --> wrong result of 0.6398198 (which is item [1,2])

As I understand rowSums needs an array rather than a vector (although not sure why). But I don't understand why the second way using sum doesn't work. Ideally, there is some way to only sum all columns in a row that lie above the diagonal.

Thanks a lot!

回答1:

The problem is you are not passing an array to rowSums:

class(m1[1,2:8])
# [1] "numeric"

This is a numeric vector. Use more than a single row and it will work just fine:

class(m1[1:2,2:8])
# [1] "matrix"

rowSums(m1[1:2,2:8])
#     iAAA       iAA 
#0.7165197 1.0000000 

If you want to sum all the columns that lie above the diagonal then you can use lower.tri to set all elements below the diagonal to 0 (or perhaps NA) and then use rowSums. If you do not want to include the diagonal elements themselves you can set diag = TRUE (thanks to @Fabio for pointing this out):

m1[lower.tri(m1 , diag = TRUE)] <- 0
rowSums(m1)
#     iAAA       iAA        iA      iBBB       iBB        iB      iCCC        iD 
#0.7165197 0.8898254 0.9451855 0.6385214 0.4405342 0.2509605 0.4165637 0.0000000 

#  With 'NA'
m1[lower.tri(m1)] <- NA
rowSums(m1,na.rm=T)
#     iAAA       iAA        iA      iBBB       iBB        iB      iCCC        iD 
#0.7165197 0.8898254 0.9451855 0.6385214 0.4405342 0.2509605 0.4165637 0.0000000