Home > database >  efficient way to fill in numbers in between in log-scale
efficient way to fill in numbers in between in log-scale

Time:04-30

log10scaleround = function(x) {
    v = log10(c(1, 2, 5, 10))
    lx = log10(x)
    10^(floor(lx)   vapply(lx %% 1, function(r) v[which.min(abs(v - r))], 0))
}
log10scaleround(c(0.2589254, 20.5671765))
[1]  0.2 20.0

The above function can round numbers in log10 scale to numbers like .1, .2, .5, 1, 2, 5, 10, 20, 50, 100.

Given a boundary like 0.2, 20.0, I want to fill in numbers in between like .5, 1, 2, 5, 10.

That is, for input like 0.2589254, 20.5671765, I want the output be c(.2, .5, 1, 2, 5, 10, 20).

I could use a for-loop to solve this problem. But it is not efficient. How to program this efficiently in R?

CodePudding user response:

I think all that was needed was usage of the outer product operator.

log10scaleround <- function(x){
  logrange <- floor(log10(x))
  fill <- c(c(1,2,5,10) %o% 10^(logrange[1]:logrange[2]))
  fill[fill >= x[1] & fill <= x[2]]
}

Which yields:

> log10scaleround(c(0.2589254, 20.5671765))
[1]  0.5  1.0  1.0  2.0  5.0 10.0 10.0 20.0

As previously stated by @jpsmith, the returned vector should not contain 0.2. If your use case does not conform to that, then removing the fill >= x[1] should sort that right out.

CodePudding user response:

Here's something that works. Maybe it could be more efficient.

logSeq <- function(x){
  lx1 = floor(log10(min(x)))
  lx2 = ceiling(log10(max(x)))
  z=rep(10^(lx1:lx2), each=3)*c(1,2,5)
  z[z>=log10scaleround(min(x))-0.001 & 
      z<=log10scaleround(max(x)) 0.001]
}

> logSeq(c(0.2589254, 20.5671765))
[1]  0.2  0.5  1.0  2.0  5.0 10.0 20.0
  •  Tags:  
  • r
  • Related