使用 NA 填充只有零的组

Fill groups that have only zeros in them with NA

提问人:uke 提问时间:11/14/2023 更新时间:11/14/2023 访问量:44

问:

我获得了一些旧数据,其中包含仅包含 s 的组。我想清理这个数据集以将其用于教学。虽然有些 s 在我的数据中自然出现,但一个组不可能只包含 s。这使我得出结论,这样一个组中的观察结果可以安全地用 s 标记。000NA

目标

我希望只有当整个小组都充满.0NA0

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

此数据表示多个关键变量唯一标识每个组的情况。

  • 在群中,一切都是。1a0
  • 在组中,有一个。2b0

我希望在例如 并保留其他组。我希望该解决方案在管道中工作,这不是强制性的,但会很好。1aNA2bdplyr

所需输出

# 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) == 0group_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
r if 语句 dplyr 案例 na

评论

1赞 Mark 11/14/2023
分组后别忘了!或使用ungroup().by =
1赞 uke 11/16/2023
有效点。就我而言,之后我需要这些小组,所以离开他们是可以的。我喜欢答案中使用的方法。.by =

答:

2赞 Gregor Thomas 11/14/2023 #1

你需要确保你为每一行获得一个。( 比基础 R 对回收更严格。在这里,组的测试值为 length-1,指定的结果 为 length-1,但所需结果的长度与组中的行数相同。NAcase_whenNA

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())valuecase_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()