在R中避免If-Then-Else结构

时间:2015-02-20 20:33:40

标签: r if-statement

我面临的任务是从矩阵列表中返回一些行。要返回的行可以输入数字或“第一”和“最后”。我编码像这样:

showrow <- function(row) {
  if (class(row) == "numeric") {
    getrow <- function(d) {
      d[row,]
    }
    return(getrow)
  } else {
    if (row =="first") {
      getrow <- function(d) {
        head(d, 1)
      }
      return(getrow)
    } else {
      if (row == "last") {
        getrow <- function(d) {
          tail(d, 1)
        }
        return(getrow)
      } else {
        stop("invalid position")
      }
    }
  }
}

然后可以这样使用它:

a <- matrix(rnorm(20), 4)
b <- matrix(rnorm(100), 10)
lst <- list(a, b) ; lst
num <- "last" # Or `num <- "first"`, or `num <- 3`, etc
lapply(lst, function(df) { showrow(num)(df) })

问题是我认为If结构看起来仍然很笨拙......在这种特殊情况下是否有任何解决方法可以避免它?


(并且,在旁注中,如果下标超出界限,例如num <- 11,是否可以返回NA?)

3 个答案:

答案 0 :(得分:1)

这是一种方法:

showrow <- function(row) {
  if (class(row) == "numeric") return(function(d) d[row,])
  f <- list(first=head,last=tail)[[row]]
  if (is.null(f)) stop("invalid position")
  function(d) f(d,1)
}

答案 1 :(得分:1)

这是一个switch解决方案。

showrow <- function(row) {
  switch(class(row),
         numeric = function(d) {
           d[row,]
         },
         character = switch(row,
                            first = function(d){
                              head(d,1)
                            },
                            last = function(d){
                              tail(d,1)
                            },
                            {stop("Invalid position")}),
        {stop("Invalid position")}
  )
}

答案 2 :(得分:1)

如果将界面更改为:

,则可以大大简化您的问题
  如果你给我一个除了数字之外的任何东西,那么

告诉我最后一行,否则显示该行:

showrow <- function(row) {
  if(!is.numeric(row)) return(function(x) tail(x, 1L))
  function(x) tryCatch(x[row, ], error=function(e) NA)
}

用法示例:

showrow("last")(a)   # Last row
showrow(4)(a)        # 4th row (also last in this case)
showrow(2:3)(a)      # 2nd and 3rd
showrow(20)(a)       # Returns NA

你不需要为#34;第一个&#34;因为1工作正常。然后你可以做这样的事情。显然showrow("first")(mx)仍会返回最后一行,这可能会令人困惑。真的最好的事情是:

  

如果我指定了它,请显示一个特定的行,如果我不指定,则显示最后一行。

这更容易实施。