I have matrix
m = matrix(c(0,-1,-2,-3,1,0,-4,-5,2,4,0,-6,3,5,6,0),4,4)
m
which is not symmetric initially
[,1] [,2] [,3] [,4]
[1,] 0 1 2 3
[2,] -1 0 4 5
[3,] -2 -4 0 6
[4,] -3 -5 -6 0
I need to melt
it first
mm = melt(m)
and only after that I would like to replace lower triangle values
> mm[melt(lower.tri(m))['value']==TRUE,]
Var1 Var2 value
2 2 1 -1
3 3 1 -2
4 4 1 -3
7 3 2 -4
8 4 2 -5
12 4 3 -6
with upper triangle values
> mm[melt(upper.tri(m))['value']==TRUE,]
Var1 Var2 value
5 1 2 1
9 1 3 2
10 2 3 4
13 1 4 3
14 2 4 5
15 3 4 6
I tried
mm[melt(lower.tri(m))['value']==TRUE,'value'] = mm[melt(upper.tri(m))['value']==TRUE,'value']
but the result
> mm
Var1 Var2 value
1 1 1 0
2 2 1 1
3 3 1 2
4 4 1 4
5 1 2 1
6 2 2 0
7 3 2 3
8 4 2 5
9 1 3 2
10 2 3 4
11 3 3 0
12 4 3 6
13 1 4 3
14 2 4 5
15 3 4 6
16 4 4 0
is not symmetric for these two values pairs
Var1 Var2 value
4 4 1 4
13 1 4 3
Var1 Var2 value
7 3 2 3
10 2 3 4
Is there a beautiful way to make the matrix after melt
symmetric by copying upper triangle values into lower triangle values?
Use the fact that Var2
(column index) for lower triangle will be smaller than the Var1
(row index).
mm$value2 = sapply(1:NROW(mm), function(i){
if (mm$Var2[i] - mm$Var1[i] < 0){
mm$value[i] = mm$value[mm$Var1 == mm$Var2[i] & mm$Var2 == mm$Var1[i]]
}else{
mm$value[i]
}
})
mm
# Var1 Var2 value value2
#1 1 1 0 0
#2 2 1 -1 1
#3 3 1 -2 2
#4 4 1 -3 3
#5 1 2 1 1
#6 2 2 0 0
#7 3 2 -4 4
#8 4 2 -5 5
#9 1 3 2 2
#10 2 3 4 4
#11 3 3 0 0
#12 4 3 -6 6
#13 1 4 3 3
#14 2 4 5 5
#15 3 4 6 6
#16 4 4 0 0