3

I have two vectors of equal length and I would like to halve the values in the first one based on a criteria from the second. As a concrete example, let

V1 = 1:6 ; V2 = c(0,0,1,1,0,1)

I would like to divide every value in V1 by 2 which corresponds to a 1 in V2.

I know how to do this using a for loop but each vector has several hundred thousand elements so it seems like there should be a much faster method.

What I am really looking for is something like the apply function but only applied to selective elements.

David Arenburg
  • 91,361
  • 17
  • 137
  • 196
sean ericson
  • 189
  • 1
  • 4
  • 9
  • 1
    What is the desired output? – David Arenburg Apr 21 '15 at 07:38
  • Thank you everyone for the help. mapply was exactly what I was looking for :-) . To answer your question David, the desired output would for the example would be (1, 2, 1.5, 2, 5, 3). For the specific project I only needed to divide by two but it is definitely great to know how to apply the concept to a general setting. Thank you all again! – sean ericson Apr 26 '15 at 02:28

2 Answers2

5
v1 = c(1:6)
v2 = c(0,0,1,1,0,1)
v1 / (v2+1)

More generally if you want an apply function, look at ?mapply

mapply(function(x1, x2) { if (x2==1) { x1/2; } else { x1 } } , v1, v2)

Here's a way to do it with data.table, which is likely to be fast...

library(data.table)
DT[v2==1,divisor:=2]
DT[v2==0,divisor:=1]
DT[,answer:=v1/divisor]
nsheff
  • 3,063
  • 2
  • 24
  • 29
  • Why do you recommend `mapply`? `ifelse` would be preferable. – Roland Apr 21 '15 at 07:49
  • 1
    @Roland What makes you think there is anything wrong with `mapply`? This should be optimized under the hood, and it is not a raw loop. – Tim Biegeleisen Apr 21 '15 at 07:54
  • 1
    @TimBiegeleisen [This question](http://stackoverflow.com/q/28983292/1412059) might be of interest to you. `mapply` can't be as efficient as a "vectorized function". – Roland Apr 21 '15 at 07:59
  • @Roland I just suggested `mapply` because the OP asked for an apply-like function... but you're probably right that it's less efficient. – nsheff Apr 21 '15 at 08:07
4
v1 <- c(1:6)
v2 <- c(0,0,1,1,0,1)

v1 / (v2 + 1)
#[1] 1.0 2.0 1.5 2.0 5.0 3.0

For using the strategy to apply a function to selected elements, you need to transform v2 to a logical vector and use it for subsetting:

as.logical(v2)
#[1] FALSE FALSE  TRUE  TRUE FALSE  TRUE
res <- v1
res[as.logical(v2)] <- res[as.logical(v2)] / 2
res
#[1] 1.0 2.0 1.5 2.0 5.0 3.0

res[as.logical(v2)]
#[1] 1.5 2.0 3.0
Roland
  • 127,288
  • 10
  • 191
  • 288