【问题标题】:Validating arguments before executing a function在执行函数之前验证参数
【发布时间】:2014-07-23 16:39:20
【问题描述】:

我想验证我传递给函数的两个参数是否有效。

为此,我正在检查我分配给“state”变量的“State”值是否在状态列表“statelist”中。然后我检查我分配给我的“测量”变量的“测量”值是否在我的测量列表“测量列表”中。如果第一次检查失败,则应生成“无效状态”错误消息。如果第二次检查失败,则应生成“无效测量”错误消息。如果两项检查都通过,我希望函数最低

这是我的数据框,“数据”:

school<-c("NYU", "BYU", "USC", "FIT", "Oswego","UCLA","USF","Columbia")
state<-c("NY","UT","CA","NY","NY","CA", "CA","NY")
measure<-c("MSAT","MSAT","GPA","MSAT","MSAT","GPA","GPA","GPA")
score<-c(590, 490, 2.9, 759, 550, 1.2, 3.1, 3.2)
data<-data.frame(school,state, measure,score)

这个函数检查我有一个有效的州缩写:

teststate<-function(state){
  statelist<-(c(state.abb,"DC","GU","MP","PR","VI"))
  if(state %in% statelist){
    testmeasure(measure)
  } else{
    stop("invalid state")
  }
 } 

此函数检查我指定的度量值是否在我的度量值列表中:

testmeasure<-function(measure){ 
    measurelist<-c("MSAT","GPA","VSAT")
    if(measure %in% measurelist){
      lowest(state, measure)
    } else{
      stop("invalid measure")
    }
  }

这是有效性检查成功后应该运行的主要功能:

lowest <- function(state, measure){
    answer<-subset(data,subset=(state==State & measure==Measure))
    order.answer<-order(answer$score,answer$school)
    answer1<-as.matrix(answer[order.answer,])
    answer1[1,1]
  }

对于这个例子:

lowest("NY","MSAT")

正确答案应该是[1]“Owsego”,但是当我完整运行代码时,它永远不会完成,控制台只是显示:

+ lowest("NY","MSAT")
+ 

当我在函数之外独立测试每个模块时,它们都可以工作。

【问题讨论】:

  • 这些加号是从哪里来的?它们通常是 R 的继续提示,这意味着您还没有关闭括号或 " 并且 R 想要更多。
  • 只是出于好奇,有没有想过使用stopifnot()
  • 我得到一个不同的错误,因为您的“最低”函数中有“状态”,但您构造的数据框的“状态”是小写的,并且 R 区分大小写。如果你解决了这个问题(并为“measure”修复了“Measure”),那么我会得到“Oswego”。

标签: r function validation arguments


【解决方案1】:

试试这个:

lowestV2 <- function(State,Measure){
  ##
  if(State %in% c(state.abb,"DC","GU","MP","PR","VI")){
    if(Measure %in% c("MSAT","GPA","VSAT")){
      answer<-subset(data,subset=(state==State & measure==Measure))
      order.answer<-order(answer$score,answer$school)
      answer1<-as.matrix(answer[order.answer,])
      answer1[1,1]
    } else {
      stop("invalid measure")
    }
  } else {
    stop("invalid state")
  }
  ##
}
##
> lowestV2("NY","MSAT")
[1] "Oswego"

除非您针对某种类型的复杂情况/条件进行错误捕获,否则您最好将处理直接包含在主函数中,而不是为每个条件调用外部错误处理函数。

【讨论】:

    【解决方案2】:

    可以使用checkmate 包(来自CRAN)进行参数检查。

    加载数据:

    school <- c("NYU", "BYU", "USC", "FIT", "Oswego","UCLA","USF","Columbia")
    stateList <- c("NY","UT","CA","NY","NY","CA", "CA","NY")
    measureList <- c("MSAT","MSAT","GPA","MSAT","MSAT","GPA","GPA","GPA")
    score <- c(590, 490, 2.9, 759, 550, 1.2, 3.1, 3.2)
    data <- data.frame(school, stateList, measureList, score)
    

    加载包,并为函数添加测试:

    library(checkmate)
    
    lowest <- function (State, Measure) {
      expect_subset(State, stateList, empty.ok=FALSE, info="invalid state")
      expect_subset(Measure, measureList, empty.ok=FALSE, info="invalid measure")
    
      # if you also want to restrict to single states and measures
      assert_atomic(State, len=1)
      assert_atomic(Measure, len=1)
    
      answer<-subset(data,subset=(stateList==State & measureList==Measure))
      order.answer<-order(answer$score,answer$school)
      answer1<-as.matrix(answer[order.answer,])
      answer1[1,1]
    }
    

    测试我们的新功能:

    lowest("NY","MSAT")
    # [1] "Oswego"
    lowest("NJ","MSAT")
    # Error with message 'invalid state'
    lowest("NY","blah")
    # Error with message 'invalid measure'
    

    【讨论】:

      【解决方案3】:

      我相信这个功能可以完成你想要的:

      school<-c("NYU", "BYU", "USC", "FIT", "Oswego","UCLA","USF","Columbia")
      state<-c("NY","UT","CA","NY","NY","CA", "CA","NY")
      measure<-c("MSAT","MSAT","GPA","MSAT","MSAT","GPA","GPA","GPA")
      score<-c(590, 490, 2.9, 759, 550, 1.2, 3.1, 3.2)
      data<-data.frame(school,state, measure,score)
      
      lowest <- function(State, Measure,Statelist,Measurelist,Data){
        if (!State%in%Statelist){
          stop("invalid state")
        }
        if (! Measure%in%Measurelist){
          stop("invalid measure")
        }
        else{
          answer<-subset(data,subset=(state==State & measure==Measure))
          order.answer<-order(answer$score,answer$school)
          answer1<-as.matrix(answer[order.answer,])
          print(answer1[1,1])
        }
      }
      
      lowest("NY","MSAT",state,measure,data)
      

      它还使您能够在不更改函数本身的情况下为函数提供不同的状态、度量和数据集列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-05
        • 2019-11-13
        • 2011-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-22
        相关资源
        最近更新 更多