Alternative to nested ifelse() statements in R

房东的猫 提交于 2020-06-17 03:30:26

问题


Problem

I need a function which computes uncertainty of measurement by an instrument for different ranges (eg. I measure electrical current and if it's in the range of 2 mA the uncertainty is 0.1 % + 3 dig of the measured value). It is better if the function is able to take a vector and return a vector instead of just numbers.

I have written the function with lots of ifs but it returns warnings the condition has length > 1 and only the first element will be used. After a while of research I have discovered that ifs in R are designed to work with an expression which evaluates to a single boolean value while ifelse can work with vectors.

But as there are about ten chained else ifs the same thing with ifelses would be rather ugly.

Example

with ifs:

S.I = function(I) {
   if(I<=(2*10^(-6))){
      0.1*I/100 + 3*10^(-9)
   } else if(I<=(20*10^(-6))) {
      ...
   }
   ...
}

with ifelses

S.I = function(I) {
   ifelse(I<=(2*10^(-6)),0.1*I/100 + 3*10^(-9),ifelse(I<=(2*10^(-6)),...,ifelse(...)))
}

Question

Is there an alternative to ifelses in this case?


回答1:


The usual way of doing this in R is probably cut; here's an example.

## some sample current values
I <- c(1e-6, 2e-6, 1e-5, 2e-5, 1e-4, 2e-4, 1e-3, 2e-3)
## define the endpoints for the different ranges
breaks <- c(-Inf, 2*10^(-6:3))
## for each range, define the percent of the original
## and the amount to add
percent <- c(0.10, 0.11, 0.12, 0.13)
dig <- c(3e-9, 3e-8, 3e-7, 3e-6) 
## get the range that each value falls in
range <- cut(I, breaks, labels=FALSE)
## and multiply by the right percent and add the right extra amount
I*percent[range]/100 + dig[range]



回答2:


As you noted, your function only works with single values as if does not act on vectors. The solution is to send each value of your vector one by one to the function.

R provides a set of apply function to do exactly that (it's like a for loop but faster) :

result = sapply(I_vector, S.I)

If you want to apply S.I several times in your code on vectors, it can be worth using a wrapper :

wrapper_S.I = function(I) { return(sapply(I_vector, S.I)) }
result = wrapper_S.I(I_vector)

NOTE: You can also create the wrapper with Vectorize:

wrapper_S.I = Vectorize(S.I)

which creates a wrapper with extra controls.



来源:https://stackoverflow.com/questions/28700107/alternative-to-nested-ifelse-statements-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!