在分组数据框中使用 case_when 时出错(因为它评估所有条件)

des*_*hen 4 r tidyverse

我有一个像这样的数据框:

\n
df <- data.frame(group   = c(1, 1, 1, 2, 2, 2),\n                 var     = c(1, 2, 3, 2, 3, 4),\n                 value   = c(1, 2, 3, 4, 5, 6),\n                 ranking = c(1, 2, 3, 1, 2, 3))\n\n  group var value ranking\n1     1   1     1       1\n2     1   2     2       2\n3     1   3     3       3\n4     2   2     4       1\n5     2   3     5       2\n6     2   4     6       3\n
Run Code Online (Sandbox Code Playgroud)\n

我想做的事:

\n

Group byvar然后取第 1 组的排名(如果group == 1该组中存在 的行),否则采用现有排名或(如果组为 2)在排名中添加某个数字。因此,通过将仅存在于一组(特别是第二组)的那些排名添加到末尾,可以算是一种“加入”排名。

\n

这是我的代码:

\n
df |> \n  group_by(var) |> \n  mutate(ranking = case_when(n() == 2   ~ ranking[group == 1],\n                             group == 1 ~ ranking,\n                             group == 2 ~ ranking + 3))\n
Run Code Online (Sandbox Code Playgroud)\n

这给出了一个错误:

\n
Error in `mutate()`:\n\xe2\x84\xb9 In argument: `ranking = case_when(...)`.\n\xe2\x84\xb9 In group 4: `var = 4`.\nCaused by error:\n! `ranking` must be size 1, not 0.\n
Run Code Online (Sandbox Code Playgroud)\n

问题是在评估ranking[group == 1]每一行时的情况,无论某些分组不会具有group == 1. 我以前遇到过这个问题,但不记得了/找到我们当时是如何解决它的。

\n

预期输出为:

\n
  group var value ranking\n1     1   1     1       1\n2     1   2     2       2\n3     1   3     3       3\n4     2   2     4       2\n5     2   3     5       3\n6     2   4     6       6\n
Run Code Online (Sandbox Code Playgroud)\n

Ron*_*hah 5

使用match而不是==应该修复它,因为:

  1. match精确返回 1 个匹配项(第一个匹配项),==如果存在则可以返回多个匹配项。
  2. 它返回NA而不是numeric(0)没有匹配时返回。
library(dplyr)

df |> 
  group_by(var) |> 
  mutate(ranking = case_when(n() == 2 ~ ranking[match(1, group)],
                             group == 1 ~ ranking,
                             group == 2 ~ranking + 3))

#   group   var value ranking
#  <dbl> <dbl> <dbl>   <dbl>
#1     1     1     1       1
#2     1     2     2       2
#3     1     3     3       3
#4     2     2     4       2
#5     2     3     5       3
#6     2     4     6       6
Run Code Online (Sandbox Code Playgroud)