Home > Mobile >  Row-wise difference between matrix and data frame
Row-wise difference between matrix and data frame

Time:02-22

I have 2 objects: m1 is a matrix that increases in rows over time, and m2 is a data frame that decreases in rows over time. Both share common column names (i.e., row, col). What I want is to find the difference between the first row of m1 and each row of m2 and have the output stored as an object in a list. This should continue for the subsequent rows of m1.

I have tried with apply(m1, 1, function(x){x - m2}), but this gives me a result I cannot explain (i.e., the difference doesn't make sense from the second observations onwards). Why is this happenning and what can be done to ensure the difference is returned as desired?

Data, code and current output:

m1 <- matrix(1:4, ncol = 2, byrow = T) 
m2 <- data.frame(matrix(1:10, ncol = 2, byrow = T))
colnames(m1) <- colnames(m2) <- c("row", "col")

> m1
     row col
[1,]   1   2
[2,]   3   4
> m2
  row col
1   1   2
2   3   4
3   5   6
4   7   8
5   9  10
> apply(m1, 1, function(x){x - m2})
[[1]]
  row col
1   0   0
2  -1  -3
3  -4  -4
4  -5  -7
5  -8  -8

[[2]]
  row col
1   2   2
2   1  -1
3  -2  -2
4  -3  -5
5  -6  -6

Desired output:

[[1]]
  row col
1   0   0
2  -2  -2
3  -4  -4
4  -6  -6
5  -8  -8

[[2]]
  row col
1   2   2
2   0   0
3  -2  -2
4  -4  -4
5  -6  -6

CodePudding user response:

We can try the code below

apply(
  m1,
  1,
  function(x) {
    t(x - t(m2))
  },
  simplify = FALSE
)

which gives

[[1]]
     row col
[1,]   0   0
[2,]  -2  -2
[3,]  -4  -4
[4,]  -6  -6
[5,]  -8  -8

[[2]]
     row col
[1,]   2   2
[2,]   0   0
[3,]  -2  -2
[4,]  -4  -4
[5,]  -6  -6

Or, another option using Map split rep

Map(
  `-`,
  split(m1[rep(1:nrow(m1), each = nrow(m2)), ], gl(nrow(m1), nrow(m2))),
  list(m2)
)

which gives

$`1`
  row col
1   0   0
2  -2  -2
3  -4  -4
4  -6  -6
5  -8  -8

$`2`
  row col
1   2   2
2   0   0
3  -2  -2
4  -4  -4
5  -6  -6

CodePudding user response:

We could use sweep

my_function <- function(m1, m2){
  x <- as.vector(m1[1,])
  y <- as.vector(m1[2,])
  m2_1 <- sweep(m2, 2, x, `-`)*-1
  m2_2 <- sweep(m2, 2, y, `-`)*-1
  list(m2_1,m2_2)
}

my_function(m1, m2)

my_function(m1, m2)
[[1]]
  X1 X2
1  0  0
2 -2 -2
3 -4 -4
4 -6 -6
5 -8 -8

[[2]]
  X1 X2
1  2  2
2  0  0
3 -2 -2
4 -4 -4
5 -6 -6

  • Related