двойной порог (вкл / выкл) с или без - PullRequest
1 голос
/ 03 декабря 2009

функция, которую я пишу, определяет поведение физического переключателя: он должен быть включен, если значение превышает верхний порог, и может снова отключаться, если он опускается ниже нижнего порога. аналогичная логика описала бы обычный термостат в домашней печи. очевидно, я хочу, чтобы он работал на векторах, вот и весь смысл!

так что если у меня есть данные

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)
}

Ответы [ 2 ]

1 голос
/ 03 декабря 2009

Палка с петлей. Если значения не являются независимыми, тогда нет никакого преимущества в использовании apply.

Если у вас нет веских причин, вам следует избегать побочных эффектов в функциях.

1 голос
/ 03 декабря 2009

Вот одно эффективное решение без петель:

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)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...