Subtract a Constant Vector from Each Row in a Matrix in R

subtract a constant vector from each row in a matrix in r

This is exactly what sweep was made for:

b <- matrix(rep(1:20), nrow=4, ncol=5)
x <- c(5,6,7)

b[,3:5] <- sweep(b[,3:5], 2, x)
b

# [,1] [,2] [,3] [,4] [,5]
#[1,] 1 5 4 7 10
#[2,] 2 6 5 8 11
#[3,] 3 7 6 9 12
#[4,] 4 8 7 10 13

..or even without subsetting or reassignment:

sweep(b, 2, c(0,0,x))

In R subtract a vector from each row of a dataframe

We can use sweep :

sweep(df1, 2, Vec, `-`)
# `-` is default FUN in sweep so you can also use
#sweep(df1, 2, Vec)

# V1 V2 V3
#1 0 3 5
#2 1 4 6
#3 2 5 7

Or an attempt similar to yours

df1 - rep(Vec, each = nrow(df1))

how to let a matrix minus vector by row rather than by column

First, let's use colMeans(m) to get column means of matrix m. Then we use sweep:

sweep(m, 2, colMeans(m))

where 2 specifies margin (we want column-wise operation, and in 2D index, the second index is for column). By default, sweep performs FUN = "-", so in above we are subtracting column means from the matrix, i.e., centring the matrix.

Similarly if we want to subtract row means from all rows, we can use:

sweep(m, 1, rowMeans(m))

You can set FUN argument to other functions, too. Another common use of sweep is for column / row rescaling, where you can read How to rescale my matrix by column or row for more.


Function scale mentioned by the other answer is used only for column-wise operation. A common use is to standardised all matrix columns. We can set scale = FALSE to perform column centring only.

scale is just a wrapper function of sweep which you can verify by inspecting the source code of sweep.default:

if (center) {
center <- colMeans(x, na.rm = TRUE)
x <- sweep(x, 2L, center, check.margin = FALSE)
}

if (scale) {
scale <- apply(x, 2L, f)
x <- sweep(x, 2L, scale, "/", check.margin = FALSE)
}

Read ?sweep, ?scale, ?colMeans for more on those functions.

Subtract vector from matrix based on data.frame efficiently

You can just match the rows:

set.seed(111)
# original data
X <- matrix(rnorm(200),100,2)

A <- data.frame(index_a = 1:4, value1 = rnorm(4), value2 = rnorm(4))
B <- data.frame(index_b = 1:4, value1 = rnorm(4), value2 = rnorm(4))

vec_a <- sample(1:4, nrow(X), replace = T)
vec_b <- sample(1:4, nrow(X), replace = T)

newX <- X - as.matrix(A[match(vec_a,A$index_a),-1]-B[match(vec_b,B$index_b),-1])

Then we run your loop:

for(iii in 1:nrow(X)){

X_clean <- A[which(A$index_a == vec_a[iii]),-1] - # subtract correct A value
B[which(B$index_b == vec_b[iii]),-1] # subtract correct B value

X_clean <- as.numeric(X_clean)
X[iii,] = X[iii,] - X_clean
}

And check the values are equal:

all.equal(c(newX),c(X))
[1] TRUE

Match should be pretty fast, but if it is still too slow, you can just call out the values of A using vec_a, like A[vec_a,] ..

Subtract the values from one matrix by row for each column of another matrix

You could use m1 - c(m2). The c() reduces a 1-column matrix to a vector. When it is subtracted from a matrix, it will recycle to the same dimention of that matrix.

> m1 <- matrix(1:15, 5, 3)

[,1] [,2] [,3]
[1,] 1 6 11
[2,] 2 7 12
[3,] 3 8 13
[4,] 4 9 14
[5,] 5 10 15

> m2 <- matrix(1:5, 5, 1)

[,1]
[1,] 1
[2,] 2
[3,] 3
[4,] 4
[5,] 5

> m1 - c(m2)

[,1] [,2] [,3]
[1,] 0 5 10
[2,] 0 5 10
[3,] 0 5 10
[4,] 0 5 10
[5,] 0 5 10


Related Topics



Leave a reply



Submit