Vicent
Vicent

Reputation: 323

Performing an operation on some elements of a vector

I know how to 'extract' some elements from a vector meeting some given condition, in R —for instance:

x = c(10, 20, 30, 40)
x[x<25]

Result:

[1] 10 20

What I would like is to apply an operation to some given elements of a vector, without either modifying or loosing the rest of elements. For instance:

x = c(10, 20, 30, 40)
y = numeric(length(x))  # create a vector with as many zeros as elements in `x`

And now, I want to make y[i] equal to 10 times x[i], only if x[i]>25, using vectorisation, of course.

Upvotes: 2

Views: 99

Answers (3)

Ronak Shah
Ronak Shah

Reputation: 388982

You could use

(x > 25) * (10 * x)
#[1]   0   0 300 400

To break it down

(x > 25) #gives
#[1] FALSE FALSE  TRUE  TRUE

(10 * x)
#[1] 100 200 300 400

Now when you multiply it together FALSE is evaluated to 0 whereas TRUE to 1. So numbers greater than 25 are multiplied by 10 whereas less than equal to 25 are multiplied to 0.


As an alternative to ifelse we can also use replace

replace(x * 10, x <= 25, 0)      
#[1]   0   0 300 400 

Bencharmking on length 1e6 data

set.seed(1234)
x <- sample(1:50, 1e6, replace = TRUE)

library(microbenchmark)
microbenchmark(mul = (x > 25) * (10 * x), 
               ifelse = ifelse(x>25, x*10, 0), 
               replace = replace(x * 10, x <= 25, 0))


Unit: milliseconds
#   expr       min        lq      mean    median        uq       max neval cld
#    mul  6.654335  12.74489  15.93877  14.22821  15.03979  70.48483   100 a  
# ifelse 89.945089 112.12242 126.15313 120.03759 135.84350 432.44697   100 c
#replace 11.711879  18.30549  27.78782  20.75061  21.96056 395.21573   100 b 


In case, if we want to keep x as it is and change only for x > 25 we can do

c(1, 10)[(x > 25) + 1] * x
#[1]  10  20 300 400

Upvotes: 2

Esben Eickhardt
Esben Eickhardt

Reputation: 3852

That is a job for ifelse:

# Your data
x = c(10, 20, 30, 40)

# Multiplying with ten if condition is met else zero
ifelse(x>25, x*10, 0)
[1]  0  0 300 400

Upvotes: 4

Vicent
Vicent

Reputation: 323

I figured how to do this. I suppose it is very easy for those who work with R on a daily basis; I post it here, just in case it helps someone:

x = c(10, 20, 30, 40)
y = numeric(length(x))  # create a vector with as many zeros as elements in `x`
ii = (x>25)  # vector of boolean values
y[ii] = 10*x[ii]  # performs the operation only on/for those elements for which `ii` is true
y

Result:

[1]   0   0 300 400

Hope you find it useful.

Upvotes: 1

Related Questions