【问题标题】:double threshold (on/off) with or without a for双阈值(开/关),带或不带 for
【发布时间】:2010-12-22 20:08:50
【问题描述】:

我正在编写的函数指定了物理开关的行为:如果一个值超过上限阈值,它应该打开,如果它低于下限阈值,它可以再次关闭。类似的逻辑将描述家用烤箱中的正常恒温器。显然我希望它在向量上起作用,这就是重点!

如果我有数据

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

问题是关于编程风格的:我首先尝试在其中使用“应用”函数编写它,但我忘记将环境考虑在内......所以我编写了一个带有“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)
}

【问题讨论】:

    标签: r


    【解决方案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)))
    

    【讨论】:

    • 嗯,你说得对,我没有解释这两个阈值之间应该发生什么,我只是给出了“通过示例”的定义......如物理家庭“烤箱逻辑”,应该保持之前的状态。 (S > 200 不计算我需要的逻辑向量)。但你的回复确实让我想起了 na.locf 函数和this other question
    【解决方案2】:

    坚持使用 for 循环。如果这些值不是独立的,那么使用 apply 没有任何优势。

    除非你有充分的理由,否则你应该避免函数的副作用。

    【讨论】:

      猜你喜欢
      • 2016-01-07
      • 1970-01-01
      • 1970-01-01
      • 2020-03-07
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多