我正在编写的函数指定物理开关的行为:如果值超过上限阈值,则应该打开;如果值低于下限阈值,则可以再次关闭。类似的逻辑将描述家用烤箱中的普通恒温器。显然我希望它能够用于向量,这就是重点!
所以,如果我有数据
S <- c(50, 100, 150, 180, 210, 200, 190, 182, 175, 185, 195, 205)
我的功能告诉烤箱温度是否正常。 “打开烤箱”的逻辑反转。
R> thresholdOnOff(S, 180, 200)
[1] FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE
关于编程风格的问题:我首先尝试使用'apply'函数编写它但我忘记考虑环境...所以我写了一个带有'for'循环的工作版本 - 我不喜欢,然后记得环境,我不确定这两个版本:
thresholdOnOff <- local( {
## following the R inferno
f <- function(series, lower, upper, initialValue=FALSE) {
status <<- initialValue
switchOnOff <- function(x) {
if(x > upper)
status <<- TRUE
if(x < lower)
status <<- FALSE
return(status)
}
sapply(series, switchOnOff)
}
} )
thresholdOnOff <- function(series, lower, upper, initialValue=FALSE) {
## just guessing and reading from the documentation
status <- initialValue
switchOnOff <- function(x) {
if(x > upper)
assign('status', TRUE, inherits=TRUE)
if(x < lower)
assign('status', FALSE, inherits=TRUE)
return(status)
}
sapply(series, switchOnOff)
}
答案 0 :(得分:1)
这是一个没有循环的有效解决方案:
library("zoo")
S <- c(50, 100, 150, 180, 210, 200, 190, 182, 175, 185, 195, 205)
thresholdOnOff <- function(x, low, high, initial.value=FALSE) {
require("zoo")
s <- rep(NA, length(x))
s[1] <- initial.value
s[x > high] <- TRUE
s[x < low] <- FALSE
return(na.locf(s))
}
thresholdOnOff(S, 180, 200)
或者,您可以在一行中使用ifelse来解决此问题,但如果您拥有大数据,那么速度会慢得多:
na.locf(ifelse(S > 200, TRUE, ifelse(S < 180, FALSE, NA)))
答案 1 :(得分:1)
坚持使用for循环。如果这些值不是独立的,则使用apply没有任何优势。
除非你有充分的理由,否则你应该避免在功能上产生副作用。