如何对组应用一系列自定义操作

How to apply a sequence of custom operations on a group by

我有以下形式的数据框:

ID Rank Var1 Var2
a 3 na 6
b 2 3 na
a 1 na 5
a 2 2 1
b 1 7 1

我正在尝试应用一系列操作:

  1. 按 ID 列分组
  2. 按排名列降序排列
  3. 对于每个变量列,select 排名最高的非 na 值 所以输出将是
ID Var1 Var 2
a 2 6
b 3 1

到目前为止我有

df %>% group_by(ID) %>% arange(desc(Rank))

但我不确定如何过滤每列的非 NA 和 select 最高值。 NA 过滤器应仅应用于列 - 如果 Var 1 具有 na,​​则应将其排除在 Var 1 的计算之外,但不适用于 Var2。

Select 分组后所选变量的第一个 non-NA 值:

library(dplyr)

df %>% 
  na_if("na") %>% 
  group_by(ID) %>% 
  arrange(desc(Rank), .by_group = T) %>% 
  summarise(across(Var1:Var2, ~ head(.x[!is.na(.x)], 1)))

# A tibble: 2 × 3
  ID    Var1  Var2 
  <chr> <chr> <chr>
1 a     2     6    
2 b     3     1    

first:

df %>% 
  na_if("na") %>% 
  group_by(ID) %>% 
  summarise(across(Var1:Var2, ~ first(.x[!is.na(.x)], order_by = "Rank")))

数据

df <- read.table(header = T, text = "ID Rank    Var1    Var2
a   3   na  6
b   2   3   na
a   1   na  5
a   2   2   1
b   1   7   1")
library(tidyverse)

tribble(
  ~ID, ~Rank, ~Var1, ~Var2,
  "a", 3, NA, 6,
  "b", 2, 3, NA,
  "a", 1, NA, 5,
  "a", 2, 2, 1,
  "b", 1, 7, 1
) |> 
  group_by(ID) |> 
  arrange(ID, desc(Rank)) |> 
  fill(everything(), .direction = "up") |> 
  summarise(across(starts_with("Var"), first))
#> # A tibble: 2 × 3
#>   ID     Var1  Var2
#>   <chr> <dbl> <dbl>
#> 1 a         2     6
#> 2 b         3     1

reprex package (v2.0.1)

于 2022-05-11 创建

另一个可能的解决方案:

library(tidyverse)

map(c("Var1", "Var2"), ~ 
      select(df, ID, Rank, all_of(.x)) %>% 
      group_by(ID) %>% 
      drop_na() %>% 
      slice_max(Rank) %>% 
      ungroup %>% select(-Rank)) %>% 
  reduce(inner_join)

#> Joining, by = "ID"
#> # A tibble: 2 x 3
#>   ID     Var1  Var2
#>   <chr> <int> <int>
#> 1 a         2     6
#> 2 b         3     1