我获得了一些旧数据,其中包含仅包含
0
的组。我想清理这个数据集以用于教学。虽然一些 0
自然出现在我的数据中,但一个组不可能只包含 0
。这使我得出这样的结论:可以安全地用 NA
来标记此类组中的观察结果。
目标
我希望
0
应该替换为 NA
只有当整组都充满了 0
。
Reprex
library(dplyr)
df <- tibble(key_1 = rep(1:2, each = 4),
key_2 = rep(letters[1:2], each = 2, times = 2),
value = c(0, 0, 0, -1, 1, 2, 1, 0))
df
#> Output
# A tibble: 8 × 3
# key_1 key_2 value
# <int> <chr> <dbl>
# 1 a 0
# 1 a 0
# 1 b 0
# 1 b -1
# 2 a 1
# 2 a 2
# 2 b 1
# 2 b 0
此数据代表了多个关键变量唯一标识每个组的情况。
1a
组,一切都是0
。2b
组中有一个0
。我希望
1a
充满 NA
,而例如2b
和其他组被保留。我希望该解决方案能够在 dplyr
管道中工作,这不是强制性的,但它会很好。
所需输出
# key_1 key_2 value
# <int> <chr> <dbl>
# 1 a NA
# 1 a NA
# 1 b 0
# 1 b -1
# 2 a 1
# 2 a 2
# 2 b 1
# 2 b 0
迄今为止的尝试
我尝试使用
dplyr::case_when()
,并将 value
列的正常值设置为后备。这会引发以下错误:
df |> group_by(key_1, key_2) |>
mutate(value = case_when(sum(value != 0) == 0 ~ NA,
.default = value))
#> Error:
# ! `.default` must have size 1, not size 2.
如果我不指定默认值,一切都是
NA
。
提供一些默认虚拟值表明条件
sum(value != 0) == 0
与 group_by
一起正常工作。
df |> group_by(key_1, key_2) |>
mutate(value = case_when(sum(value != 0) == 0 ~ NA,
.default = "default"))
#> Output
# A tibble: 8 × 3
# Groups: key_1, key_2 [4]
# key_1 key_2 value
# <int> <chr> <chr>
# 1 a NA
# 1 a NA
# 1 b default
# 1 b default
# 2 a default
# 2 a default
# 2 b default
# 2 b default
您需要确保每行都有一个
NA
。 (case_when
对于回收比基本R更严格一些。在这里,您的测试值是组的长度-1,但您想要的结果与组中的行数具有相同的长度。)
df |>
mutate(
value = case_when(all(value == 0) ~ rep(NA, n()), .default = value),
.by = c(key_1, key_2)
)
# # A tibble: 8 × 3
# key_1 key_2 value
# <int> <chr> <dbl>
# 1 1 a NA
# 2 1 a NA
# 3 1 b 0
# 4 1 b -1
# 5 2 a 1
# 6 2 a 2
# 7 2 b 1
# 8 2 b 0
df |>
mutate(all_0 = all(value == 0), .by = c(key_1, key_2)) |>
mutate(value = if_else(all_0, NA, value))