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
Run a Bash Script from an R Script
Join Data.Table on Exact Date or If Not the Case on the Nearest Less Than Date
How to Run an 'R' Script Without Suppressing Output
Sub-Assign by Reference on Vector in R
R Shiny Conditionalpanel Output Value
How to Annotate() Ggplot with Latex
Merge Data Frames and Overwrite Values
Extracting Value Based on Another Column
Data.Table Inner/Outer Join with Na in Join Column of Type Double Bug
Applying the Same Factor Levels to Multiple Variables in an R Data Frame
How to Exit a Shiny App and Return a Value
Scatterplot with Color Groups - Base R Plot
Devtools::Install_Github Fails with Ca Cert Error