R 如何在自定义函数中包含逻辑检查

R 如何在自定义函数中包含逻辑检查,r,function,if-statement,R,Function,If Statement,我编写了一个自定义函数,它对一列数据执行数学变换,输入为数据和另一个输入(温度)。我想要两种不同的逻辑检查。第一个问题是列中的任何值是否超过某个阈值,因为转换在阈值之上和之下是不同的。第二个是检查温度输入是否高于某个值,在这种情况下,发出警告,指出高于阈值的值是异常的,并检查数据 现在,我用一系列if/else语句编写了这个函数。但是,这是一个警告,它仅使用T/F语句字符串的第一个元素。我的函数的简化示例如下: myfun = function(temp,data) { if(temp

我编写了一个自定义函数,它对一列数据执行数学变换,输入为数据和另一个输入(温度)。我想要两种不同的逻辑检查。第一个问题是列中的任何值是否超过某个阈值,因为转换在阈值之上和之下是不同的。第二个是检查温度输入是否高于某个值,在这种情况下,发出警告,指出高于阈值的值是异常的,并检查数据

现在,我用一系列if/else语句编写了这个函数。但是,这是一个警告,它仅使用T/F语句字符串的第一个元素。我的函数的简化示例如下:

myfun = function(temp,data) {
    if(temp > 34){
    warning('Temperature higher than expected')
  }
    if (data > 50) {
      result = temp*data
      return(result)
    } else if(data <= 50) {
      result = temp/data
      return(result)
    }
  }

myfun(temp = c(25,45,23,19,10), data = c(30,40,NA,50,10))
myfun=函数(温度、数据){
如果(温度>34){
警告('温度高于预期')
}
如果(数据>50){
结果=温度*数据
返回(结果)

}否则如果(数据代码的主要问题是,您将所有值作为向量传递给函数,但随后要进行单元素比较。您需要将元素逐个传递给函数,或者将某种向量化比较或for循环放入函数中。下面是for循环方法,这可能是这是最不优雅的方式,但至少很容易理解发生了什么

另一个问题是,在传递到任何条件语句之前,NA显然需要在数据向量中进行处理,否则会出现错误

最后一个问题是当数据=50时该怎么办。现在你有大于或小于50的条件测试,但正如你所见,数据中的第4点是50,所以现在你得到了NA

myfun = function(temp,data) {
    result <- rep(NA,length(temp))
    for (t in 1:length(temp)) {
        if(temp[t] > 34) {
            warning('Temperature higher than expected')
            if (!is.na(data[t])) {
                if (data [t] > 50) {
                    result[t] <- temp[t]*data[t]
                } else if(data[t] < 50) {
                    result[t] <- temp[t]/data[t]

                }
            }
        } else {
            if (!is.na(data[t])) {
                if (data[t] > 50) {
                    result[t] <- temp[t]*data[t]

                } else if(data[t] < 50) {
                    result[t] <- temp[t]/data[t]

                }
            }
        }
    }
    return(result)
}

代码的主要问题是,将所有值作为向量传递给函数,然后进行单元素比较。您需要将元素逐个传递给函数,或者将某种向量化比较或for循环放入函数中。下面是for循环方法,这可能是最小的方法这样做很优雅,但至少很容易理解发生了什么

另一个问题是,在传递到任何条件语句之前,NA显然需要在数据向量中进行处理,否则会出现错误

最后一个问题是当数据=50时该怎么办。现在你有大于或小于50的条件测试,但正如你所见,数据中的第4点是50,所以现在你得到了NA

myfun = function(temp,data) {
    result <- rep(NA,length(temp))
    for (t in 1:length(temp)) {
        if(temp[t] > 34) {
            warning('Temperature higher than expected')
            if (!is.na(data[t])) {
                if (data [t] > 50) {
                    result[t] <- temp[t]*data[t]
                } else if(data[t] < 50) {
                    result[t] <- temp[t]/data[t]

                }
            }
        } else {
            if (!is.na(data[t])) {
                if (data[t] > 50) {
                    result[t] <- temp[t]*data[t]

                } else if(data[t] < 50) {
                    result[t] <- temp[t]/data[t]

                }
            }
        }
    }
    return(result)
}

看起来你对数据变量中的if语句做了同样的事情,不管temp是否大于50。因此,与其将该部分写两次,为什么只写一盎司,在temp if语句之外?@提问者是的,你完全正确,这将简化函数并使其更易于阅读。我们e
ifelse
用于矢量化版本。建议复制。这将处理您的转换,但我建议将警告转换为类似于
if(any(temp>34))警告(“某些温度高于预期”)
@Gregor谢谢,if(any()建议真的很有用。我会尝试一下ifelse。我已经考虑过了,但我并不总是喜欢它,因为你最终会得到嵌套的ifelse语句,而这些语句可能很难阅读。是的,嵌套的
ifelse
可能会让人讨厌。但是在这种情况下,你只有一个条件,所以不需要嵌套:
ifelse(数据>50,temp*data,temp/data)
。比较一下,这一行相当于您接受的答案中的大约20行。而且效率也会更高……避免嵌套太深时使用
ifelse
。但是这样的情况非常适合
ifelse
。看起来您对数据变量中的if语句做了同样的事情,而不管是什么温度>50。因此,与其将该部分写两次,为什么只写一盎司,不在temp if语句中?@提问者是的,你完全正确,这将简化函数并使其更易于阅读。使用
ifelse
作为矢量化版本。建议重复。这将处理你的转换但是我建议将警告转换为类似于
if(any(temp>34))警告(“某些温度高于预期”)
@Gregor谢谢,if(any)()建议真的很有用。我会尝试一下ifelse。我已经考虑过了,但我并不总是喜欢它,因为你最终会得到嵌套的ifelse语句,而这些语句可能很难阅读。是的,嵌套的
ifelse
可能会让人讨厌。但是在这种情况下,你只有一个条件,所以不需要嵌套:
ifelse(数据>50,temp*data,temp/data)
。比较一下,在你接受的答案中,一行相当于大约20行。而且效率也会更高……避免嵌套太深时使用
ifelse
。但是这样的情况非常适合
ifelse
。这是有道理的。这应该是肯定的,使用apply变量可能会更快,但是理解正在发生的事情可能会有点困难…我经常发现速度的提高不值得理解。无论如何,在多个向量上使用apply函数时请检查这一点:这是有道理的。这应该是肯定的,使用apply变量可能会更快,但理解wh可能会有点困难在进行中…我经常发现速度的提高不值得理解。无论如何,在多个向量上使用应用函数时,请查看以下内容: