Reputation: 367
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 if
s 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 if
s 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 if
s the same thing with ifelse
s would be rather ugly.
with if
s:
S.I = function(I) {
if(I<=(2*10^(-6))){
0.1*I/100 + 3*10^(-9)
} else if(I<=(20*10^(-6))) {
...
}
...
}
with ifelse
s
S.I = function(I) {
ifelse(I<=(2*10^(-6)),0.1*I/100 + 3*10^(-9),ifelse(I<=(2*10^(-6)),...,ifelse(...)))
}
Is there an alternative to ifelse
s in this case?
Upvotes: 1
Views: 2012
Reputation: 37714
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]
Upvotes: 3
Reputation: 2436
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.
Upvotes: 1