2

I have a matrix mat that looks like:

      A     B     C     D      E     F
1  0.74  1.19  0.01  1.21  16000  0.02
2  0.76  1.17  0.01  1.21  15500  0.02
3  0.79  1.16  0.01  1.17  15625  0.02
4  0.75  1.17  0.01  1.17  15600  0.02
5  0.80  1.19  0.01  1.19  15225  0.02
6  0.79  1.18  0.01  1.18  15625  0.02

And I want to build a Symmetric matrix from this by applying the function Sum(Col1-Col2). The end result will look something like this:

    A     B     C     D      E     F
A   0
B         0
C               0
D                     0
E                            0
F                                  0

Such that the blank spaces represent the sum of difference. i.e. [1,2] = Sum(A-B).

I have investigated methods such as:

combs<-combn(names(mat),2)
val<-apply(combs,2,function(x) mat[[x[1]]]-mat[[x[2]]])

But it doesn't give me a nice symmetric matrix.

Anyone have any ideas?

Thanks.

EDIT - Thanks to Troy the above works. But how about if I want to compute Sum((Col1-Col2)^2) in that Sum(((A_1,A_2,..,A_n)-(B_1,B_2,..,B_n))^2) (so can't sum A and B initially and then subtract otherwise the answer will be off).

Travis Liew
  • 787
  • 1
  • 11
  • 34

2 Answers2

2
mat<-as.matrix(read.table(text="A     B     C     D      E     F
0.74  1.19  0.01  1.21  16000  0.02
0.76  1.17  0.01  1.21  15500  0.02
0.79  1.16  0.01  1.17  15625  0.02
0.75  1.17  0.01  1.17  15600  0.02
0.80  1.19  0.01  1.19  15225  0.02
0.79  1.18  0.01  1.18  15625  0.02", header=T))


cross<-expand.grid(apply(mat,2,sum),apply(mat,2,sum))
matrix(cross[,1]-cross[,2],6)

[,1]     [,2]     [,3]     [,4]      [,5]     [,6]
[1,]     0.00    -2.43     4.57    -2.50 -93570.37     4.51
[2,]     2.43     0.00     7.00    -0.07 -93567.94     6.94
[3,]    -4.57    -7.00     0.00    -7.07 -93574.94    -0.06
[4,]     2.50     0.07     7.07     0.00 -93567.87     7.01
[5,] 93570.37 93567.94 93574.94 93567.87      0.00 93574.88
[6,]    -4.51    -6.94     0.06    -7.01 -93574.88     0.00

for second question, how about this?

EDIT - think I put the bracket in the wrong place

apply(mat,2,function(x)colSums((matrix(x,ncol(mat),ncol(mat))-mat)^2))
#             A            B           C            D          E            F
#A 0.000000e+00 9.881000e-01 3.48390e+00 1.048400e+00 1459547504 3.393100e+00
#B 9.881000e-01 0.000000e+00 8.16740e+00 2.100000e-03 1459471669 8.028000e+00
#C 3.483900e+00 8.167400e+00 0.00000e+00 8.332500e+00 1459690004 6.000000e-04
#D 1.048400e+00 2.100000e-03 8.33250e+00 0.000000e+00 1459469476 8.191700e+00
#E 1.459548e+09 1.459472e+09 1.45969e+09 1.459469e+09          0 1.459688e+09
#F 3.393100e+00 8.028000e+00 6.00000e-04 8.191700e+00 1459688132 0.000000e+00
Troy
  • 8,581
  • 29
  • 32
  • Thank @Troy. Now if I want to do `Sum((A-B)^2)`, how would I go about doing it? I think the main issue here is that I can't sum `A` and `B` then subtract initially, I need to do this operation on EACH row of each column. So something like `Sum(((A_1,A_2,..,A_n)-(B_1,B_2,..,B_n))^2)`. Thanks! – Travis Liew Jan 27 '14 at 09:31
2

This seems valid, too:

outer(colSums(mat), colSums(mat), `-`)  #I used Troy's `mat`
#         A        B        C        D         E        F
#A     0.00    -2.43     4.57    -2.50 -93570.37     4.51
#B     2.43     0.00     7.00    -0.07 -93567.94     6.94
#C    -4.57    -7.00     0.00    -7.07 -93574.94    -0.06
#D     2.50     0.07     7.07     0.00 -93567.87     7.01
#E 93570.37 93567.94 93574.94 93567.87      0.00 93574.88
#F    -4.51    -6.94     0.06    -7.01 -93574.88     0.00

EDIT to match edited question:

n = seq_len(ncol(mat))
ff = function(a, b) sum((mat[,a] - mat[,b]) ^ 2)
outer(n, n, Vectorize(ff))
#             [,1]         [,2]        [,3]         [,4]       [,5]         [,6]
#[1,] 0.000000e+00 9.881000e-01 3.48390e+00 1.048400e+00 1459547504 3.393100e+00
#[2,] 9.881000e-01 0.000000e+00 8.16740e+00 2.100000e-03 1459471669 8.028000e+00
#[3,] 3.483900e+00 8.167400e+00 0.00000e+00 8.332500e+00 1459690004 6.000000e-04
#[4,] 1.048400e+00 2.100000e-03 8.33250e+00 0.000000e+00 1459469476 8.191700e+00
#[5,] 1.459548e+09 1.459472e+09 1.45969e+09 1.459469e+09          0 1.459688e+09
#[6,] 3.393100e+00 8.028000e+00 6.00000e-04 8.191700e+00 1459688132 0.000000e+00
alexis_laz
  • 12,884
  • 4
  • 27
  • 37
  • Thanks @alexis_laz, I edited the question so am in need of some further help! :) – Travis Liew Jan 27 '14 at 09:34
  • Yep absolutely! That was it, thanks. I had just worked out a really roundabout and no doubt inefficient way of doing it. Your solution is much better. Thanks! – Travis Liew Jan 27 '14 at 09:57