我有一个嵌套的if_else
里面的声明mutate
。在我的示例数据框中:
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
我希望分组依据a
然后根据组中是否有一行或两行来执行操作。我本以为这是嵌套的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.
该示例的设置方式,当第一个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
)?
EDIT正如答案中所述,要么没有临时的tmp_check
列并使用if ... else
构造,或使用以下有效但会产生警告的代码:
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)])
)