How to divide each row of a matrix by elements of a vector in R
Here are a few ways in order of increasing code length:
t(t(mat) / dev)
mat / dev[col(mat)] # @DavidArenburg & @akrun
mat %*% diag(1 / dev)
sweep(mat, 2, dev, "/")
t(apply(mat, 1, "/", dev))
plyr::aaply(mat, 1, "/", dev)
mat / rep(dev, each = nrow(mat))
mat / t(replace(t(mat), TRUE, dev))
mapply("/", as.data.frame(mat), dev) # added later
mat / matrix(dev, nrow(mat), ncol(mat), byrow = TRUE) # added later
do.call(rbind, lapply(as.data.frame(t(mat)), "/", dev))
mat2 <- mat; for(i in seq_len(nrow(mat2))) mat2[i, ] <- mat2[i, ] / dev
Data Frames
All the solutions that begin with mat /
also work if mat
is a data frame and produce a data frame result. The same is also the case for the sweep
solution and the last, i.e. mat2
, solution. The mapply
solutions works with data.frames but produces a matrix.
Vector
If mat
is a plain vector rather than a matrix then either of these return a one column matrix
t(t(mat) / dev)
mat / t(replace(t(mat), TRUE, dev))
and this one returns a vector:
plyr::aaply(mat, 1, "/", dev)
The others give an error, warning or not the desired answer.
Benchmarks
The brevity and clarity of the code may be more important than speed but for purposes of completeness here are some benchmarks using 10 repetitions and then 100 repetitions.
library(microbenchmark)
library(plyr)
set.seed(84789)
mat<-matrix(runif(1e6),nrow=1e5)
dev<-runif(10)
microbenchmark(times=10L,
"1" = t(t(mat) / dev),
"2" = mat %*% diag(1/dev),
"3" = sweep(mat, 2, dev, "/"),
"4" = t(apply(mat, 1, "/", dev)),
"5" = mat / rep(dev, each = nrow(mat)),
"6" = mat / t(replace(t(mat), TRUE, dev)),
"7" = aaply(mat, 1, "/", dev),
"8" = do.call(rbind, lapply(as.data.frame(t(mat)), "/", dev)),
"9" = {mat2 <- mat; for(i in seq_len(nrow(mat2))) mat2[i, ] <- mat2[i, ] / dev},
"10" = mat/dev[col(mat)])
giving:
Unit: milliseconds
expr min lq mean median uq max neval
1 7.957253 8.136799 44.13317 8.370418 8.597972 366.24246 10
2 4.678240 4.693771 10.11320 4.708153 4.720309 58.79537 10
3 15.594488 15.691104 16.38740 15.843637 16.559956 19.98246 10
4 96.616547 104.743737 124.94650 117.272493 134.852009 177.96882 10
5 17.631848 17.654821 18.98646 18.295586 20.120382 21.30338 10
6 19.097557 19.365944 27.78814 20.126037 43.322090 48.76881 10
7 8279.428898 8496.131747 8631.02530 8644.798642 8741.748155 9194.66980 10
8 509.528218 524.251103 570.81573 545.627522 568.929481 821.17562 10
9 161.240680 177.282664 188.30452 186.235811 193.250346 242.45495 10
10 7.713448 7.815545 11.86550 7.965811 8.807754 45.87518 10
Re-running the test on all those that took <20 milliseconds with 100 repetitions:
microbenchmark(times=100L,
"1" = t(t(mat) / dev),
"2" = mat %*% diag(1/dev),
"3" = sweep(mat, 2, dev, "/"),
"5" = mat / rep(dev, each = nrow(mat)),
"6" = mat / t(replace(t(mat), TRUE, dev)),
"10" = mat/dev[col(mat)])
giving:
Unit: milliseconds
expr min lq mean median uq max neval
1 8.010749 8.188459 13.972445 8.560578 10.197650 299.80328 100
2 4.672902 4.734321 5.802965 4.769501 4.985402 20.89999 100
3 15.224121 15.428518 18.707554 15.836116 17.064866 42.54882 100
5 17.625347 17.678850 21.464804 17.847698 18.209404 303.27342 100
6 19.158946 19.361413 22.907115 19.772479 21.142961 38.77585 100
10 7.754911 7.939305 9.971388 8.010871 8.324860 25.65829 100
So on both these tests #2 (using diag
) is fastest. The reason may lie in its almost direct appeal to the BLAS, whereas #1 relies on the costlier t
.
Dividing columns of a matrix by elements of a vector
You could use sweep
for this:
#same as apply the second argument needs to be 1 for row or 2 for column
sweep(a, 2, b, FUN = '/')
# [,1] [,2] [,3]
#[1,] 0.3333333 0.50 0.6
#[2,] 1.3333333 1.25 1.2
#[3,] 2.3333333 2.00 1.8
R: How to divide columns in matrix by a vector ?
This is perfect use case for sweep
-
sweep(matrix, MARGIN = 2, STATS = vector, `/`)
[,1] [,2] [,3] [,4] [,5]
[1,] 0.5 1.25 3.000000 2.6 8.5
[2,] 1.0 1.50 3.333333 2.8 9.0
[3,] 1.5 1.75 3.666667 3.0 9.5
[4,] 2.0 2.00 4.000000 3.2 10.0
Dividing each row of a dataframe matrix by a vector with a shorter length in R?
You can use sweep
.
sweep(type.convert(d[, -1]), 2, crow_sqm, `/`)
# Crow_education_Omer Crow_education_Keisha Crow_education_Kate Crow_education_Winston
#[1,] 206.0 123 10.0 207.5
#[2,] 208.0 123 10.2 207.5
#[3,] 208.5 121 10.2 209.0
# Crow_education_Marlin
#[1,] NA
#[2,] NA
#[3,] NA
Or with transpose.
t(t(type.convert(d[, -1]))/crow_sqm)
The data is a matrix and matrix can have data of only one type. The 1st column cannot be represented as number hence all the values in the matrix turns to be of type character. -1
is used to drop 1st column in the matrix and type.convert
is used to change values from character to numeric for all the columns.
Divide every row in a matrix by corresponding row in vector
We can do this by dividing with rowMaxs
(from matrixStats
)
library(matrixStats)
mat/rowMaxs(mat)
divide rows of a matrix by a column vector
Transpose the matrix, multiply it by a diagonal matrix whose entries are the reciprocals of the entries in your column vector, and then transpose the result.
x <- matrix(1:16, 4)
v <- c(1:4)
t(t(x) %*% diag(1 / v)) v <- c(1:4)
t(t(x) %*% diag(1 / v))
How to divide each element in a row by corresponding row value?
Here is one option with tidyverse
. We divide all the columns except the 'Ac' column with the 'Ac', then summarise_all
to return the sum
if any non-NA element is present or else return NA
library(tidyverse)
df %>%
transmute_at(-1, list(~ ./Ac)) %>%
summarise_all(list(~ if(all(is.na(.))) NA else sum(.,na.rm = TRUE)))
# V1 V2 V3 V4 V5 V6 V7
#1 NA 0 9.821429 3.690476 0 0.8484848 0.9188312
It can also be done in a single step
df %>%
summarise_at(-1, list(~ if(all(is.na(.))) NA else (sum(./Ac, na.rm = TRUE)) ))
# V1 V2 V3 V4 V5 V6 V7
#1 NA 0 9.821429 3.690476 0 0.8484848 0.9188312
Update
Based on the comments,
df %>%
summarise_at(-1, list(~ if(all(is.na(.))) NA
else if(sum(is.na(.)) == 1) (sum(./Ac, na.rm = TRUE))
else (sum(Ac* ., na.rm = TRUE)/sum(Ac, na.rm = TRUE)) ))
# V1 V2 V3 V4 V5 V6 V7
#1 NA 0 9.821429 3.690476 0 2.464 2.904
Same method can be translated to data.table
as well
library(data.table)
setDT(df)[, lapply(.SD, function(x) if(all(is.na(x))) NA
else sum(x/Ac, na.rm = TRUE)), .SDcols = 2:ncol(df)]
# V1 V2 V3 V4 V5 V6 V7
#1: NA 0 9.821429 3.690476 0 0.8484848 0.9188312
Updated data.table solution
setDT(df)[, lapply(.SD, function(x) if(all(is.na(x))) NA
else if(sum(is.na(x)) == 1) (sum(x/Ac, na.rm = TRUE))
else (sum(Ac* x, na.rm = TRUE)/sum(Ac, na.rm = TRUE)) ), .SDcols = 2:ncol(df)]
# V1 V2 V3 V4 V5 V6 V7
#1: NA 0 9.821429 3.690476 0 2.464 2.904
data
df <- structure(list(Ac = c(6.6, 8.4), V1 = c(NA_real_, NA_real_),
V2 = c(NA, 0), V3 = c(NA, 82.5), V4 = c(NA, 31), V5 = c(0,
0), V6 = c(5.6, 0), V7 = c(5.2, 1.1)), class = "data.frame",
row.names = c(NA,
-2L))
Divide each data frame row by vector in R
sweep
is useful for these sorts of operations, but it requires a matrix as input. As such, convert your data frame to a matrix, do the operation and then convert back. For example, some dummy data where we divide each element in respective columns of matrix mat
by the corresponding value in the vector vec
:
mat <- matrix(1:25, ncol = 5)
vec <- seq(2, by = 2, length = 5)
sweep(mat, 2, vec, `/`)
In use we have:
> mat
[,1] [,2] [,3] [,4] [,5]
[1,] 1 6 11 16 21
[2,] 2 7 12 17 22
[3,] 3 8 13 18 23
[4,] 4 9 14 19 24
[5,] 5 10 15 20 25
> vec
[1] 2 4 6 8 10
> sweep(mat, 2, vec, `/`)
[,1] [,2] [,3] [,4] [,5]
[1,] 0.5 1.50 1.833333 2.000 2.1
[2,] 1.0 1.75 2.000000 2.125 2.2
[3,] 1.5 2.00 2.166667 2.250 2.3
[4,] 2.0 2.25 2.333333 2.375 2.4
[5,] 2.5 2.50 2.500000 2.500 2.5
> mat[,1] / vec[1]
[1] 0.5 1.0 1.5 2.0 2.5
To convert from a data frame use as.matrix(df)
or data.matrix(df)
, and as.data.frame(mat)
for the reverse.
Dividing rows by terms of a vector in R
It seems that you want to divide each column by the vector.
a <- matrix(c(3,9,6,12), 2)
dev <- c(5,10)
a/dev
[,1] [,2]
[1,] 0.6 1.2
[2,] 0.9 1.2
Here, the vector dev
is extended to the length of a
by recycling. Since a
stores the data column-wise, the division returns the result of dividing each column by dev
.
Related Topics
Long/Bigint/Decimal Equivalent Datatype in R
Conditional Replacement of Values in a Data.Frame
Filtering a Data Frame on a Vector
Use of Ggplot() Within Another Function in R
Plotting Lines and the Group Aesthetic in Ggplot2
Find How Many Times Duplicated Rows Repeat in R Data Frame
Combining Paste() and Expression() Functions in Plot Labels
Ggplot Legends - Change Labels, Order and Title
Putting Mathematical Symbols and Subscripts Mixed With Regular Letters
How Does One Reorder Columns in a Data Frame
Capitalize the First Letter of Both Words in a Two Word String
Reasons For Using the Set.Seed Function
How to Change Multiple Date Formats in Same Column
Read All Files in Directory and Apply Multiple Functions to Each Data Frame
Converting Multiple Columns from Character to Numeric Format in R