'Do subtraction between columns of a data.frame

The database below presents the ranking of three methods, which I called M1, M2 and M3. Therefore, I would like to make a new dataset with the difference between the ranks of two methods. In this case, the following relation would be, M1 and M2, M1 and M3, M2 and M3. Therefore, the dataset will have three columns (n, M1-M2, M1-M3 and M2-M3).

result<-structure(list(n = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 
28, 29), M1 = c(1L, 29L, 28L, 27L, 25L, 26L, 24L, 20L, 21L, 
22L, 23L, 15L, 12L, 17L, 18L, 19L, 16L, 13L, 14L, 5L, 6L, 7L, 
8L, 9L, 10L, 11L, 4L, 2L, 3L), M2 = c(1, 29, 28, 27, 26, 25, 
24, 23, 22, 21, 20, 15, 12, 19, 18, 17, 16, 14, 13, 11, 10, 9, 
8, 7, 6, 5, 4, 3, 2), M3 = c(1L, 29L, 28L, 27L, 25L, 26L, 24L, 
20L, 21L, 22L, 23L, 15L, 12L, 17L, 18L, 19L, 16L, 13L, 14L, 5L, 
6L, 7L, 8L, 9L, 10L, 11L, 4L, 2L, 3L)), class = "data.frame", row.names = c(NA,-29L))
  
    > result
    n M1 M2 M3
1   1  1  1  1
2   2 29 29 29
3   3 28 28 28
4   4 27 27 27
5   5 25 26 25
6   6 26 25 26
7   7 24 24 24
8   8 20 23 20
9   9 21 22 21
10 10 22 21 22
11 11 23 20 23
12 12 15 15 15
13 13 12 12 12
14 14 17 19 17
15 15 18 18 18
16 16 19 17 19
17 17 16 16 16
18 18 13 14 13
19 19 14 13 14
20 20  5 11  5
21 21  6 10  6
22 22  7  9  7
23 23  8  8  8
24 24  9  7  9
25 25 10  6 10
26 26 11  5 11
27 27  4  4  4
28 28  2  3  2
29 29  3  2  3
  
r


Solution 1:[1]

We can try

cbind(
  result,
  `colnames<-`(
    combn(result[-1], 2, function(v) v[[1]] - v[[2]]),
    combn(names(result)[-1], 2, function(v) paste0(v, collapse = "-"))
  )
)

which gives

    n M1 M2 M3 M1-M2 M1-M3 M2-M3
1   1  1  1  1     0     0     0
2   2 29 29 29     0     0     0
3   3 28 28 28     0     0     0
4   4 27 27 27     0     0     0
5   5 25 26 25    -1     0     1
6   6 26 25 26     1     0    -1
7   7 24 24 24     0     0     0
8   8 20 23 20    -3     0     3
9   9 21 22 21    -1     0     1
10 10 22 21 22     1     0    -1
11 11 23 20 23     3     0    -3
12 12 15 15 15     0     0     0
13 13 12 12 12     0     0     0
14 14 17 19 17    -2     0     2
15 15 18 18 18     0     0     0
16 16 19 17 19     2     0    -2
17 17 16 16 16     0     0     0
18 18 13 14 13    -1     0     1
19 19 14 13 14     1     0    -1
20 20  5 11  5    -6     0     6
21 21  6 10  6    -4     0     4
22 22  7  9  7    -2     0     2
23 23  8  8  8     0     0     0
24 24  9  7  9     2     0    -2
25 25 10  6 10     4     0    -4
26 26 11  5 11     6     0    -6
27 27  4  4  4     0     0     0
28 28  2  3  2    -1     0     1
29 29  3  2  3     1     0    -1

Solution 2:[2]

result = cbind(n=result$n,(result[,c(2:4)] - result[,c(3,4,2)])[,c(1,3,2)])
names(result)=c("n", "M1-M2", "M1-M3", "M2-M3")

Output:

    n M1-M2 M1-M3 M2-M3
1   1     0     0     0
2   2     0     0     0
3   3     0     0     0
4   4     0     0     0
5   5    -1     0     1
6   6     1     0    -1
7   7     0     0     0
8   8    -3     0     3
9   9    -1     0     1
10 10     1     0    -1
11 11     3     0    -3
12 12     0     0     0
13 13     0     0     0
14 14    -2     0     2
15 15     0     0     0
16 16     2     0    -2
17 17     0     0     0
18 18    -1     0     1
19 19     1     0    -1
20 20    -6     0     6
21 21    -4     0     4
22 22    -2     0     2
23 23     0     0     0
24 24     2     0    -2
25 25     4     0    -4
26 26     6     0    -6
27 27     0     0     0
28 28    -1     0     1
29 29     1     0    -1

Solution 3:[3]

Its a dataframe so you should be able to do something like

result$M1_M2 <- result$M1 - result$M2

or something similar

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ThomasIsCoding
Solution 2 langtang
Solution 3 Nad Pat