提问人:uke 提问时间:11/14/2023 更新时间:11/14/2023 访问量:44
使用 NA 填充只有零的组
Fill groups that have only zeros in them with NA
问:
我获得了一些旧数据,其中包含仅包含 s 的组。我想清理这个数据集以将其用于教学。虽然有些 s 在我的数据中自然出现,但一个组不可能只包含 s。这使我得出结论,这样一个组中的观察结果可以安全地用 s 标记。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
为 default 提供一些虚拟值表明该条件与 一起正常工作。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
答:
2赞
Gregor Thomas
11/14/2023
#1
你需要确保你为每一行获得一个。( 比基础 R 对回收更严格。在这里,组的测试值为 length-1,指定的结果 为 length-1,但所需结果的长度与组中的行数相同。NA
case_when
NA
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
评论
0赞
uke
11/14/2023
现在我终于理解了文档:“ 必须是大小 1 或与从中计算出的常见大小相同 ” [使用的公式在哪里 ]。您强制“通用大小”等于当前组的长度,从而允许将 用作默认值。这很好地突出了正在发生的事情以及为什么我之前收到错误:因为我的“通用大小”是 1,因为我只使用了 .这就是为什么我会接受这个答案,即使其他答案也很好。?case_when
.default
...
...
~
~ rep(NA, n())
value
case_when()
~ NA
1赞
Gregor Thomas
11/14/2023
是的,重复测试也可以,尽管这对我来说不太可读。value = case_when(rep(all(value == 0), n()) ~ NA, .default = value)
1赞
Jon Spring
11/14/2023
#2
df |>
mutate(all_0 = all(value == 0), .by = c(key_1, key_2)) |>
mutate(value = if_else(all_0, NA, value))
3赞
stefan
11/14/2023
#3
另一种选择是使用 :if ... else ...
library(dplyr, warn = FALSE)
df |>
group_by(key_1, key_2) |>
mutate(
value = if (any(value != 0)) value else NA
)
#> # A tibble: 8 × 3
#> # Groups: key_1, key_2 [4]
#> 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
评论
1赞
uke
11/14/2023
这显然是更优雅和可读的解决方案。我只接受了这个答案,因为它解释了为什么我的代码不起作用。为了清晰易读,这个是我的最爱。case_when()
评论
ungroup()
.by =
.by =