R get all combinations for columns and perform a function on them returning a Symmetric matrix?

StackOverflow https://stackoverflow.com/questions/21374958

Вопрос

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).

Это было полезно?

Решение

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

Другие советы

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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top