【问题标题】:Strange behavior of ifelse() in R: when are the values evaluated? [duplicate]R 中 ifelse() 的奇怪行为:何时评估值? [复制]
【发布时间】:2020-09-06 20:26:07
【问题描述】:

我有以下数据:

df = data.frame(
  stat = c('mean', 'var'),
  value = c(-9, 10))

假设如果“stat”是“var”,我想取“value”的平方,如果不是,则什么都不做。

df %>% 
  mutate(
   value = ifelse(stat=='var', sqrt(value), value))

我收到警告:

Warning message:
In sqrt(-9) : NaNs produced

为什么我会收到警告?不应该计算值 sqrt(-9) 因为“价值”是“平均”

【问题讨论】:

  • 需要复数。无法获取 -root
  • 它没有回答这个问题。 ifelse() 应该仅在 value == 'var' 时计算 sqrt()。如果没有,它应该让值保持原样。所以应该计算 sqrt(10) 但不是 sqrt(-9)。
  • 链接问题中有很好的解释。
  • 我刚刚更新了下面的答案,以展示如何在没有外部软件包的情况下使用 ifelse。

标签: r if-statement nan sqrt


【解决方案1】:

您不需要包来执行此操作:

df = data.frame(stat = c('mean', 'var'),
                value = c(-9, 10))
computed = df[df$stat == 'var','value'] %>% sqrt

如果您希望覆盖原始值,则不要覆盖第二行:

df[df$stat == 'var','value'] = df[df$stat == 'var','value'] %>% sqrt

如果你想使用原生ifelse 那么:

ifelse(df$stat =="var",sqrt(df$value),df$value)

【讨论】:

  • 您的computed 语句中的引号过多
【解决方案2】:

根据ifelse 文档

 If ‘yes’ or ‘no’ are too short, their elements are recycled.
 ‘yes’ will be evaluated if and only if any element of ‘test’ is
 true, and analogously for ‘no’.

您已将其解释为以 elementwise 方式绕过 yes 或 no。

但是,这似乎不是文档的意思。这意味着,除非测试中的所有元素要么为真要么为假,否则将进行评估。

这意味着,只要您的测试至少有一个为真,至少一个为假,那么将为测试中的每个元素预先计算“是”和“否”,并且只有在评估了该元素之后,相应的响应被选中。

【讨论】:

    【解决方案3】:

    我在评论中提到过这个问题:

    Using ifelse in R when one of the options produces NAs?

    引用作者的话: “发生的情况是,我们对整个向量进行计算,并根据测试条件替换 'p' 的值。对于 sqrt,负值肯定会给出警告并输出为 NaN。而 NaN 元素不显示在输出中,警告已经被打印出来了。警告是一个友好的警告,但可以用 suppressWarnings 抑制"

    【讨论】:

      【解决方案4】:

      您的问题“何时评估值?”的答案是:这取决于。

      如果所有元素都是TRUE,则根本不会计算第三个参数。如果所有参数都是FALSE,则不会计算第二个参数。

      但是,如果至少有一个 TRUE 和一个 FALSE,那么它们都会被完全评估。

      ifelse(c(TRUE, TRUE), "good", stop("error"))
      #> [1] "good" "good"
      
      ifelse(c(FALSE, FALSE), "good", stop("error"))
      #> Error in ifelse(c(FALSE, FALSE), "good", stop("error")) : error
      
      ifelse(c(TRUE, FALSE), "good", stop("error"))
      #> Error in ifelse(c(TRUE, FALSE), "good", stop("error")) : error
      

      【讨论】:

        猜你喜欢
        • 2013-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多