gpt4 book ai didi

r - 为什么嵌套的 ifelse 在 dplyr 0.5.0 变异中产生不正确的结果?

转载 作者:行者123 更新时间:2023-12-05 08:56:28 24 4
gpt4 key购买 nike

考虑以下数据框:

(tmp_df <-
structure(list(class = c(0L, 0L, 1L, 1L, 2L, 2L), logi = c(TRUE,
FALSE, TRUE, FALSE, TRUE, FALSE), val = c(1, 1, 1, 1, 1, 1),
taken = c(1.00684931506849, 0.993197278911565, 1.025, 0.975609756097561,
1.00826446280992, 0.991803278688525)), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -6L), .Names = c("class",
"logi", "val", "taken")))

它创建:

Source: local data frame [6 x 4]

class logi val taken
<int> <lgl> <dbl> <dbl>
1 0 TRUE 1 1.0068493
2 0 FALSE 1 0.9931973
3 1 TRUE 1 1.0250000
4 1 FALSE 1 0.9756098
5 2 TRUE 1 1.0082645
6 2 FALSE 1 0.9918033

我想按类别分组,如果每个组包含两个成员,则如果logi == FALSE,则从val中减去1,否则,减去最小值taken 来自 val 的那个组。如果每个组不包含两个成员,那么我们从 val 中减去零。

使用 dplyr 包完成上述操作的代码可以使用以下方式表示:

tmp_df %>%
group_by(class) %>%
mutate(taken_2 = ifelse(n() != 2, 0,
ifelse(logi, min(taken), 1)),
not_taken = val - taken_2)

但是,这会产生不正确的结果,其中第二个 ifelse 总是解析为第一个条件:

Source: local data frame [6 x 6]
Groups: class [3]

class logi val taken taken_2 not_taken
<int> <lgl> <dbl> <dbl> <dbl> <dbl>
1 0 TRUE 1 1.0068493 0.9931973 0.006802721
2 0 FALSE 1 0.9931973 0.9931973 0.006802721
3 1 TRUE 1 1.0250000 0.9756098 0.024390244
4 1 FALSE 1 0.9756098 0.9756098 0.024390244
5 2 TRUE 1 1.0082645 0.9918033 0.008196721
6 2 FALSE 1 0.9918033 0.9918033 0.008196721

如果我们没有第一个 ifelse 语句,也可以产生正确的结果。

tmp_df %>%
group_by(class) %>%
mutate(taken_2 = ifelse(logi, min(taken), 1),
not_taken = val - taken_2)

制作:

Source: local data frame [6 x 6]
Groups: class [3]

class logi val taken taken_2 not_taken
<int> <lgl> <dbl> <dbl> <dbl> <dbl>
1 0 TRUE 1 1.0068493 0.9931973 0.006802721
2 0 FALSE 1 0.9931973 1.0000000 0.000000000 # correct!
3 1 TRUE 1 1.0250000 0.9756098 0.024390244
4 1 FALSE 1 0.9756098 1.0000000 0.000000000 # correct!
5 2 TRUE 1 1.0082645 0.9918033 0.008196721
6 2 FALSE 1 0.9918033 1.0000000 0.000000000 # correct!

通过检查其他成功执行类似操作的代码片段,我们可以看到这个问题似乎与 mutate 和嵌套的 ifelse 无关:

tmp_df %>%
group_by(class) %>%
mutate(taken_2 = ifelse(n() != 3, 0,
ifelse(logi, min(taken), 1)),
not_taken = val - taken_2)

tmp_df_2 <-
tmp_df %>%
filter(row_number() <= 2)

(tmp_df_2$taken_2 <-
ifelse(c(0, 0), 0,
ifelse(tmp_df_2$logi, min(tmp_df_2$taken), 1)))

## but the following does not work (checks problem is not to do with grouping)
# tmp_df_2 %>%
# mutate(taken_2 = ifelse(n() != 2, 0,
# ifelse(logi, min(taken), 1)),
# not_taken = val - taken_2)

为什么会这样,我怎样才能获得预期的行为?解决方法是将嵌套的 ifelse 逻辑拆分为多个内联突变:

tmp_df %>%
group_by(class) %>%
mutate(taken_2 = ifelse(n() != 2, 0, 1),
taken_3 = taken_2 * ifelse(logi, min(taken), 1),
not_taken = val - taken_3)

其他人已经发现嵌套 ifelse 存在类似问题,但我不知道它是否具有相同的根: ifelse using dplyr results in NAs for some records

最佳答案

您是 ifelse 矢量回收的受害者。他们的关键是这一行:

mutate(taken_2 = ifelse(n() != 2, 0, 
ifelse(logi, min(taken), 1))

因为 n() != 2 是 length-1(对于每个组),ifelse 只考虑第一个 logi 并重复/回收这个值。

您应该使用 ifif_else:

mutate(taken_2 = if (n() != 2) 0 else if_else(logi, min(taken), 1))

我建议从不使用ifelse。从一个几乎由于这个错误而导致数百万美元错误的人那里拿走它。

关于r - 为什么嵌套的 ifelse 在 dplyr 0.5.0 变异中产生不正确的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40354668/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com