[R] updating elements of a vector sequentially - is there a faster way?

Noia Raindrops noia.raindrops at gmail.com
Fri Aug 24 11:37:29 CEST 2012


Hello,

Each block of probs range from p00 to p10 is last value before the block.

Example:
  probs: .1 .1 .5 .5 .5 .9 .9
  vec1 :  0  0  0  0  0  1  1
  
  probs: .9 .9 .5 .5 .5 .1 .1
  vec1 :  1  1  1  1  1  0  0

So you can eliminate a loop.


# modification 
f5 <- function () {
  vec1 <- as.numeric(as.character(cut(probs, breaks = c(0, p00, p10, 1), labels = c(0, 0.5, 1), include.lowest = TRUE, right = FALSE)))
  # = ifelse(probs < p10, ifelse(probs < p00, 0, 0.5), 1)
  vec1 <- replace(vec1, 1, 0)
  vec1 <- rle(vec1)
  vec1 <- within(unclass(vec1), values[values == 0.5] <- values[which(values == 0.5) - 1])
  vec1 <- inverse.rle(vec1)
  vec1
}

# original
f1 <- function() {
  vec1 <- rep(0, length(probs))
  for (i in 2:length(probs)) {
    vec1[i] <- ifelse(vec1[i-1] == 0,
                 ifelse(probs[i] < p10, 0, 1),
                 ifelse(probs[i] < p00, 0, 1))
  }
  vec1
}

f2 <- function(vec1) {
  val.p10 <- ifelse(probs < p10, 0, 1)
  val.p00 <- ifelse(probs < p00, 0, 1)
  vec1 <- rep(0, length(probs))
  for (i in 2:length(probs)) {
    vec1[i] <- if(vec1[i-1] == 0) val.p10[i] else val.p00[i]
  }
  vec1
}

f3 <- function () {
  a10 <- ifelse(probs < p10, 0, 1)
  a00 <- ifelse(probs < p00, 0, 1)
  vec1 <- ifelse(a10 == a00, a10, NA)
  vec1[1] <- 0
  n <- length(vec1)
  while (any(is.na(vec1))) {
    shift <- c(NA, vec1[-n])
    vec1 <- ifelse(is.na(vec1), shift, vec1)
  }
  vec1
}

f4 <- function () {
  a10 <- ifelse(probs < p10, 0, 1)
  a00 <- ifelse(probs < p00, 0, 1)
  vec1 <- ifelse(a10 == a00, a10, NA)
  vec1[1] <- 0
  n <- length(vec1)
  while (1) {
    i <- which(is.na(vec1))
    if (length(i) == 0) break
    vec1[i] <- vec1[i-1]
  }
  vec1
}

set.seed(1)
probs <- runif(10000)
p10 <- 0.6
p00 <- 0.4

identical(f1(), f2())
## [1] TRUE
identical(f1(), f3())
## [1] TRUE
identical(f1(), f4())
## [1] TRUE
identical(f1(), f5())
## [1] TRUE

# with random probs
rbenchmark::benchmark(f1(), f2(), f3(), f4(), f5(), columns = c("test", "replications", "elapsed", "relative"), replications = 100)
##   test replications elapsed  relative
## 1 f1()          100  31.456 42.279570
## 2 f2()          100   4.879  6.557796
## 3 f3()          100   2.503  3.364247
## 4 f4()          100   0.939  1.262097
## 5 f5()          100   0.744  1.000000

# with biased probs
probs <- rep(0.5, 1000)
rbenchmark::benchmark(f1(), f2(), f3(), f4(), f5(), columns = c("test", "replications", "elapsed", "relative"), replications = 100)
##   test replications elapsed   relative
## 1 f1()          100   2.917  30.385417
## 2 f2()          100   0.448   4.666667
## 3 f3()          100  32.439 337.906250
## 4 f4()          100   3.635  37.864583
## 5 f5()          100   0.096   1.000000


-- 
Noia Raindrops
noia.raindrops at gmail.com




More information about the R-help mailing list