当前位置: 首页 > 知识库问答 >
问题:

当逻辑条件意味着不应该评估输出时,为什么这个嵌套if_else中的dplyr错误?

卫开济
2023-03-14

我在 mutate 中有一个嵌套的 if_else 语句。在我的示例数据框中:

tmp_df2 <- data.frame(a = c(1,1,2), b = c(T,F,T), c = c(1,2,3))

  a     b c
1 1  TRUE 1
2 1 FALSE 2
3 2  TRUE 3

我希望按< code>a分组,然后根据一个组是一行还是两行来执行操作。我认为这个嵌套的< code>if_else就足够了:

tmp_df2 %>%
    group_by(a) %>%
    mutate(tmp_check = n() == 1) %>%
    mutate(d = if_else(tmp_check, # check for number of entries in group
                       0,
                       if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)])
    )
    )

但这会抛出错误:

Error in eval(substitute(expr), envir, enclos) : 
  `false` is length 2 not 1 or 1.

该示例的设置方式是,当第一个< code>if_else(n() == 1)条件的计算结果为true时,将返回一个元素,但当它的计算结果为false时,将返回一个包含两个元素的向量,我假设这是导致错误的原因。然而,从逻辑上讲,这种说法对我来说似乎是合理的。

以下两个语句生成(所需的)结果:

> tmp_df2 %>%
+     group_by(a) %>%
+     mutate(d = ifelse(rep(n() == 1, n()), # avoid undesired recycling
+                        0,
+                        if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)])
+     )
+     )
Source: local data frame [3 x 4]
Groups: a [2]

      a     b     c     d
  <dbl> <lgl> <dbl> <dbl>
1     1  TRUE     1   3.0
2     1 FALSE     2   1.5
3     2  TRUE     3   0.0

或者只是过滤,以便只留下包含两行的组:

> tmp_df2 %>%
+     group_by(a) %>%
+     filter(n() == 2) %>%
+     mutate(d = if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)]))
Source: local data frame [2 x 4]
Groups: a [1]

      a     b     c     d
  <dbl> <lgl> <dbl> <dbl>
1     1  TRUE     1   3.0
2     1 FALSE     2   1.5

我有三个问题。

>

  • dplyr如何知道由于逻辑条件,不应该评估的第二个输出无效?

    如何在dplyr中获得所需的行为(不使用ifelse)?

    如回答中所述进行编辑,或者不具有临时tmp_check列并使用if…elseconstruct,或者使用以下有效但产生警告的代码:

    library(dplyr)
    tmp_df2 %>%
        group_by(a) %>%
        mutate(tmp_check = n() == 1) %>%
        mutate(d = if (tmp_check)  # check for number of entries in group
                           0 else
                           if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)])
        )
    
  • 共有1个答案

    宇文育
    2023-03-14

    dplyr“知道”,因为if_else检查要用于True和False情况的值。这在?if_else中说明,源代码告诉我们它是如何完成的:

    if_else
    # function (condition, true, false, missing = NULL) 
    # {
    #     if (!is.logical(condition)) {
    #         stop("`condition` must be logical", call. = FALSE)
    #     }
    #     out <- true[rep(NA_integer_, length(condition))]
    #     out <- replace_with(out, condition & !is.na(condition), true, 
    #         "`true`")
    #     out <- replace_with(out, !condition & !is.na(condition), 
    #         false, "`false`")
    #     out <- replace_with(out, is.na(condition), missing, "`missing`")
    #     out
    # }
    # <environment: namespace:dplyr>
    

    检查replace_with的源代码:

    dplyr:::replace_with
    # function (x, i, val, name) 
    # {
    #     if (is.null(val)) {
    #         return(x)
    #     }
    #     check_length(val, x, name)
    #     check_type(val, x, name)
    #     check_class(val, x, name)
    #     if (length(val) == 1L) {
    #         x[i] <- val
    #     }
    #     else {
    #         x[i] <- val[i]
    #     }
    #     x
    # }
    # <environment: namespace:dplyr>
    

    因此,将检查 True 和 False 事例的值的长度。

    要获得您想要的行为,您可以使用if…else,正如另一位SO用户在您前面的问题中所建议的:

    tmp_df2 %>%
        group_by(a) %>%
        mutate(d = if (n() == 1) 0 else if_else(b, sum(c)/c[b == T], sum(c)/c[which(b != T)])
        )
    
     类似资料:
    • 我想创建一个

    • 问题内容: 鉴于这段JavaScript代码… 有人可以向我解释这种技术叫什么(我的最佳猜测是这个问题的标题!)?以及它如何/为什么确切起作用? 我的理解是,将为变量分配第一个变量的最接近的值(从左到右),该变量的值不为null或未定义,但是我没有设法找到有关此技术的大量参考资料,并且看到它用了很多。 另外,这项技术是否专门针对JavaScript?我知道在PHP中执行类似操作会导致具有真正的布尔

    • 我是java编程新手,不知道这些错误的含义: 源代码: 程序的名称与类的名称相同,我找到了解决方案。当我删除类中的public player和playgame时,程序没有出现错误,但我仍然无法理解错误的含义。请帮帮我

    • 我有一个数据集是这样排列的: 在这个数据集中,ID应该按时间顺序通过每个阶段(A、B、C、D),并在最后达到赢/输(ID 003和006) 但是,有时 ID 向后移动 (ID 005),其他 ID 跳过阶段(ID 001 和 004),而有些则直接转到赢/输(ID 002 和 007)。 我想用dplyr mutate逻辑调用这些。输出: 我知道我应该用类似这样的逻辑,但是我我就是想不通。 提前感

    • 我想弄明白那个错误是什么。当我将mongoDB放到另一个实例中时,它就开始发生了。 错误有一个很大的信息,但它没有说什么,也没有已知的触发它的操作。 错误消息图像: .