How to Divide Each Row of a Matrix by Elements of a Vector in R

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



Leave a reply



Submit