Reputation: 3
I have a matrix and I would like to perform a calculation on each number in the matrix so that I get another matrix with the same dimensions only with the results of the calculation. This should be easy except that part of the equation is dependent on which row I am accessing because I will need to have an internal reference to the number at column [,2] within that same row.
The equation I would like to apply is: output_matrix value = (input_matrix value at a given position) - (input_matrix value in the same row at column[,2])
For example, For [1,1] in the matrix the calculation would be 1-5
For position [1,2] in the matrix, the calculation would be 5-5
for position [2,1] in the matrix, the calculation would be 2-6
input_matrix<- matrix(1:12, nrow = 4, ncol = 3)
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
The output matrix should end up looking like this:
[,1] [,2] [,3]
[1,] -4 0 4
[2,] -4 0 4
[3,] -4 0 4
[4,] -4 0 4
I have tried doing something like this:
output_matrix<-apply(input_matrix, MARGIN=1, function(x) x-x[2])
but that gives me the following output which kind of looks like the correct matrix but flipped on it's side.
[,1] [,2] [,3] [,4]
[1,] -4 -4 -4 -4
[2,] 0 0 0 0
[3,] 4 4 4 4
I am not sure if there is a way to get the output in the same orientation as my input_matrix or if it is okay to just transpose the columns and rows? I know that if I use
t(output_matrix)
Transposing the matrix in this way does give me the correct matrix and the correct orientation, but it concerns me that the output orientations are flipped in the original calculation and I would like to understand if there is a better way to do this where the output is in the same orientation as the input from the start? And is there any case where doing the calculation in this way and them transposing it would lead to issues?
Any help would be greatly appreciated.
Upvotes: 0
Views: 28
Reputation: 887501
With apply
and MARGIN = 1
, it transposes the output, we need to transpose it
t(apply(input_matrix, MARGIN=1, function(x) x-x[2]))
-output
# [,1] [,2] [,3]
#[1,] -4 0 4
#[2,] -4 0 4
#[3,] -4 0 4
#[4,] -4 0 4
Or another option is sweep
which does the same by specifying the MARGIN
as 1, and it returns the output in the same direction
sweep(input_matrix, 1, input_matrix[,2], `-`)
-output
# [,1] [,2] [,3]
#[1,] -4 0 4
#[2,] -4 0 4
#[3,] -4 0 4
#[4,] -4 0 4
Upvotes: 1
Reputation: 145965
This is all about the recycling, which can be tricky sometimes if you want rows but it does columns, but in this case it works in your favor and you can use -
directly:
input_matrix - input_matrix[, 2]
# [,1] [,2] [,3]
# [1,] -4 0 4
# [2,] -4 0 4
# [3,] -4 0 4
# [4,] -4 0 4
Upvotes: 2