首页 > 解决方案 > R if/else 在函数中

问题描述

我正在尝试让以下函数用于处理属性,但我无法让 if elseif 在函数中工作。它给出了以下错误:“条件长度> 1,仅使用第一个元素”。我希望有人可以提出解决方案或替代方案。

例子:

x <- data.frame(runif(100, 0, 100))
colnames(x) <- "test"

WINSORIZE <- function(x){
  WIN_MEAN <- mean(x)
  WIN_SD <- sd(x)
  WIN_UPPER <- sum(WIN_MEAN + (3 * WIN_SD))
  WIN_LOWER <- sum(WIN_MEAN - (3 * WIN_SD))
  if(x > WIN_UPPER){ 
    WIN_UPPER
  } else if (x < WIN_LOWER) {WIN_LOWER
    } else x
}

WINSORIZE(x$test)

标签: rfunctionif-statement

解决方案


解决方案

使用 R 的内在矢量化能力。通过分配选择[并更改值。<-

这个解决方案非常R-ish:

winsorize <- function(x) {
  m <- mean(x)
  s <- sd(x)
  u <- m + 3 * s
  l <- m - 3 * s
  x[ x > u ] <- u      # select elements > u and assign to them u in situ
  x[ x < l ] <- l      # select elements < l and assign to them l in situ
  x                    # return the resulting vector
}

而且这个解决方案非常R适合已经矢量化的ifelse()函数:

winsorize <- function(x) {
  m <- mean(x)
  s <- sd(x)
  u <- m + 3 * s
  l <- m - 3 * s
  ifelse( x > u, u, ifelse( x < l, l, x))
}

解决方案sapply()

另一种可能性是使用sapply(x, ...)将 if-else 构造应用于 x 的每个元素。

winsorize <- function(x){
  m <- mean(x)
  s <- sd(x)
  upper <- m + 3 * s
  lower <- m - 3 * s
  # apply your if-else construct on each individual element (el) of x
  # using `sapply()`
  sapply(x, function(el) if(el > upper){ 
    upper
  } else if (el < lower) {
    lower
  } else {
    el})
}

或与以下内容相同ifelse()

winsorize <- function(x){
  m <- mean(x)
  s <- sd(x)
  upper <- m + 3 * s
  lower <- m - 3 * s
  sapply(x, function(el) 
   ifelse(el > upper, upper, ifelse(el < lower, lower, el))
}

解决方案Vectorize()

或者从你的构造中创建一个函数,在你应用它之前if-else使用这个函数向量化它:Vectorize()x

winsorize <- function(x){
  m <- mean(x)
  s <- sd(x)
  upper <- m + 3 * s
  lower <- m - 3 * s
  # define function for one element
  winsorize.one.element <- function(el) {
    if(el > upper){ upper } else if (el < lower) { lower } else { el}
  }
  # Vectorize this function
  winsorize.elements <- Vectorize(winsorize.one.element)
  # Apply the vectorized function to the vector and return the result
  winsorize.elements(x)
}

这个winsorize.one.element函数可以写得更整洁ifelse,但是虽然ifelse是矢量化的


推荐阅读