替代 R 中嵌套的 ifelse() 语句
Alternative to nested ifelse() statements in R
问题
我需要一个函数来计算仪器在不同范围内的测量不确定度(例如,我测量电流,如果它在 2 mA 的范围内,则不确定度是测量值的 0.1 % + 3 dig
)。如果函数能够接受一个向量和 return 一个向量而不只是数字,那就更好了。
我编写的函数有很多 if
,但它 return 有警告 the condition has length > 1 and only the first element will be used
。经过一段时间的研究,我发现 R 中的 if
s 设计用于处理计算结果为单个布尔值的表达式,而 ifelse
可以处理向量。
但是因为有大约十个链式 else if
s 与 ifelse
s 相同的东西会相当难看。
例子
与 if
s:
S.I = function(I) {
if(I<=(2*10^(-6))){
0.1*I/100 + 3*10^(-9)
} else if(I<=(20*10^(-6))) {
...
}
...
}
和 ifelse
s
S.I = function(I) {
ifelse(I<=(2*10^(-6)),0.1*I/100 + 3*10^(-9),ifelse(I<=(2*10^(-6)),...,ifelse(...)))
}
问题
在这种情况下,是否有 ifelse
s 的替代方案?
如您所述,您的函数仅适用于单个值,因为 if
不适用于向量。解决方案是将向量的每个值一一发送给函数。
R 提供了一组 apply
函数来执行此操作(类似于 for 循环但速度更快):
result = sapply(I_vector, S.I)
如果您想在向量代码中多次应用 S.I
,使用包装器是值得的:
wrapper_S.I = function(I) { return(sapply(I_vector, S.I)) }
result = wrapper_S.I(I_vector)
注意: 您还可以使用 Vectorize
创建包装器:
wrapper_S.I = Vectorize(S.I)
创建一个带有额外控件的包装器。
在R
中通常的做法可能是cut
;这是一个例子。
## 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 mA 的范围内,则不确定度是测量值的 0.1 % + 3 dig
)。如果函数能够接受一个向量和 return 一个向量而不只是数字,那就更好了。
我编写的函数有很多 if
,但它 return 有警告 the condition has length > 1 and only the first element will be used
。经过一段时间的研究,我发现 R 中的 if
s 设计用于处理计算结果为单个布尔值的表达式,而 ifelse
可以处理向量。
但是因为有大约十个链式 else if
s 与 ifelse
s 相同的东西会相当难看。
例子
与 if
s:
S.I = function(I) {
if(I<=(2*10^(-6))){
0.1*I/100 + 3*10^(-9)
} else if(I<=(20*10^(-6))) {
...
}
...
}
和 ifelse
s
S.I = function(I) {
ifelse(I<=(2*10^(-6)),0.1*I/100 + 3*10^(-9),ifelse(I<=(2*10^(-6)),...,ifelse(...)))
}
问题
在这种情况下,是否有 ifelse
s 的替代方案?
如您所述,您的函数仅适用于单个值,因为 if
不适用于向量。解决方案是将向量的每个值一一发送给函数。
R 提供了一组 apply
函数来执行此操作(类似于 for 循环但速度更快):
result = sapply(I_vector, S.I)
如果您想在向量代码中多次应用 S.I
,使用包装器是值得的:
wrapper_S.I = function(I) { return(sapply(I_vector, S.I)) }
result = wrapper_S.I(I_vector)
注意: 您还可以使用 Vectorize
创建包装器:
wrapper_S.I = Vectorize(S.I)
创建一个带有额外控件的包装器。
在R
中通常的做法可能是cut
;这是一个例子。
## 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]