【问题标题】:How to include logical checks in a custom function如何在自定义函数中包含逻辑检查
【发布时间】:2019-01-09 19:01:18
【问题描述】:

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

现在,我用一系列 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))

如您所见,因为它只使用 if/else 语句的第一个值,所以它没有正确计算返回值,因为它没有在转换的两个版本之间切换。此外,它只检查第一个温度值是否高于阈值。我怎样才能让它正确地将逻辑检查应用于每个值,而不仅仅是第一个值?

-edit-根据@The_Questioner 的建议简化函数并将

【问题讨论】:

  • 无论温度是否 > 50,您似乎都在对数据变量中的 if 语句做同样的事情。所以,与其把这部分写出两次,为什么只注意在临时 if 语句之外写成盎司?
  • @The_Questioner 是的,你是完全正确的,这将简化功能并使其更容易阅读。
  • ifelse 用于矢量化版本。建议重复vectorized if in R。这将处理您的转换,但我建议将警告转换为 if(any(temp &gt; 34)) warning("Some temperatures higher than expected")
  • @Gregor 谢谢,if(any() 建议真的很有帮助。我会试试 ifelse。我已经考虑过了,但我并不总是喜欢它,因为你最终得到了嵌套的 ifelse语句比难以阅读。
  • 是的,嵌套的ifelse 可能很烦人。但在这种情况下,您只有一个条件,因此不需要嵌套:ifelse(data &gt; 50, temp * data, temp / data)。比较一下,在您接受的答案中,一行相当于大约 20 行。而且它也将更加更有效率......当嵌套太深时避免ifelse。但是这样的情况非常适合ifelse

标签: r function if-statement


【解决方案1】:

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

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

最后一个问题是当 data = 50 时该怎么办。现在您有条件测试大于或小于 50,但正如您所见,data 是 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)
}

输出:

> myfun(temp = c(25,45,23,19,10), data = c(30,40,NA,50,10))
[1] 0.8333333 1.1250000        NA        NA 1.0000000

【讨论】:

  • 这是有道理的。那应该是
  • 是的,使用 apply 变体可能会更快,但理解发生了什么可能有点棘手......我经常发现速度的提高不值得理解成本.无论如何,请查看在多个向量上使用应用函数:stackoverflow.com/questions/35352647/…
猜你喜欢
  • 1970-01-01
  • 2011-01-21
  • 2019-05-27
  • 2021-05-15
  • 1970-01-01
  • 1970-01-01
  • 2013-02-24
  • 1970-01-01
  • 2011-02-13
相关资源
最近更新 更多