Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selectively Modify Indices

Tags:

r

Is there a shorter way to select elements and modify them? For example, in

y[y < 1] <- y[y < 1]*2

the object y is referenced 4 times in one line. Is it possible to reduce this repetition?

like image 693
chris Avatar asked Oct 23 '12 01:10

chris


3 Answers

Here's a construct that reduces the number of references to y by 1:

y <- -2:2
y[i] <- y[i <- y < 1] * 10

y
# [1] -20 -10   0   1   2

In practice, though, I'm more likely to do this, which is maybe less "clever" but is certainly much easier to parse (for a human):

i <- y < 2
y[i] <- y[i] * 10
like image 110
Josh O'Brien Avatar answered Sep 20 '22 01:09

Josh O'Brien


Try this

y <- y*{{y<1} + 1} 

In general you can introduce a function f

f <- function(bool) ifelse(bool, 2, 1)
y <- y * f(y < 1) 

This approach seems a bit faster than Josh's solution

n <- 10000
y <- sample(c(1,-1), n, replace = TRUE)
f1 <- function(y){y[i] <- y[i <- y < 1] * 10; y}
f2 <- function(y){y <- y*{{y<1} + 1}; y} 
benchmark(f1(y), f2(y), replications = 50000)
  test replications elapsed relative user.self sys.self user.child sys.child
1 f1(y)        50000   30.29    2.398    27.427    3.146          0         0
2 f2(y)        50000   12.63    1.000     9.859    2.918          0         0
like image 45
Ryogi Avatar answered Sep 21 '22 01:09

Ryogi


This does not reduce the number of references to y, but it does stop y>1 being calculated twice

y <- ifelse(y<1, y, y *2)

or you could predefine y <1

replacing <- y < 1

Then the line only contains two explicit references to y

y[replacing] <- y[replacing] *2 

You could put y in a data.table, and then you can (almost) reduce the number of times y is repeated by 1

 library(data.table)
 Y <- data.table(y = y)

 Y[y <1, y := y*2]

I say almost, because if you want to access the atomic vector y, you will need to type Y[,y]

like image 40
mnel Avatar answered Sep 22 '22 01:09

mnel