Mace
Mace

Reputation: 1269

Conditional element wise division in R

I have the following two matrices:

> dat <- cbind(c(1,1,2,3),c(55,23,65,67))
> dat
     [,1] [,2]
[1,]    1   55
[2,]    1   23
[3,]    2   65
[4,]    3   67
> cond <- cbind(c(1,2,3),c(0.9,1,1.1))
> cond
     [,1] [,2]
[1,]    1  0.9
[2,]    2  1.0
[3,]    3  1.1

Now, I would like to divide column 2 of dat with column 2 of cond conditional on the rows having the same value in column 1. That is:

55/0.9
23/0.9
65/1
67/1.1

How do I do that easily in R? I am also interested in solutions for data.frames.

Thanks!

Upvotes: 0

Views: 817

Answers (3)

Carl Witthoft
Carl Witthoft

Reputation: 21502

FWIW,

Rgames> cond<-cbind(1:100,runif(100))
Rgames> dat<-cbind(sample(1:100,1e5,rep=TRUE),runif(1e5))
Rgames> library(microbenchmark)
Rgames> microbenchmark(brodie(dat,cond),shadow(dat,cond),times=10)
Unit: milliseconds
              expr        min         lq     median        uq
 brodie(dat, cond)   4.981001   5.411622   6.082569  21.57764
 shadow(dat, cond) 289.586938 304.098892 309.919966 353.00062
       max neval
  72.83944    10
 372.19423    10

Upvotes: 2

BrodieG
BrodieG

Reputation: 52637

You can do this with match assuming cond is unique in column 1:

dat[, 2] / cond[match(dat[, 1], cond[, 1]), 2]
# [1] 61.11111 25.55556 65.00000 60.90909

This will be faster than merge. What match does is it finds the the index of the values in cond that match the value in dat, which you can then use to retrieve the values from cond. This will also work with data frames.

To understand what match is doing, try looking at the result of:

match(dat[, 1], cond[, 1])

Upvotes: 4

shadow
shadow

Reputation: 22303

As @Anand Mahto suggested, merge the two matrices, then the calculation becomes simple:

df <- merge(dat, cond, by=1)
df[,2]/df[,3]

Upvotes: 2

Related Questions