如何为每个组添加一行并赋值

How to add a row to each group and assign values

我有这个问题:

library(tibble)
library(dplyr)

df <- tibble(id = c("one", "two", "three"),
             A = c(1,2,3), 
             B = c(4,5,6))

  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 two       2     5
3 three     3     6

我想在每个组中添加一行 AND 为新列赋值 BUT 使用一个函数(这里是新行在每组中应该得到 A=4 B = 列的第一组值 B USING first(B)-> 期望输出:

id        A     B
<chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     6
5 two       2     5
6 two       4     5

到目前为止我已经尝试过:

如果我使用 add_row 在未分组的小标题中添加一行 -> 这个 完美 !

df %>% 
  add_row(A=4, B=4)

  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 two       2     5
3 three     3     6
4 NA        4     4

如果我尝试在分组小标题中使用 add_row -> 这不起作用:

df %>% 
  group_by(id) %>%
  add_row(A=4, B=4)

Error: Can't add rows to grouped data frames.
Run `rlang::last_error()` to see where the error occurred.

根据这个 post 我们可以使用 group_modify -> 这个 效果很好:

df %>% 
  group_by(id) %>% 
  group_modify(~ add_row(A=4, B=4, .x))

  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     4
5 two       2     5
6 two       4     4

我想将列 B 的第一个值分配给列 B(或者它可以是任何函数 min(B)max(B) etccc。)-> 这个不工作:

df %>% 
  group_by(id) %>% 
  group_modify(~ add_row(A=4, B=first(B), .x))

Error in h(simpleError(msg, call)) : 
  Fehler bei der Auswertung des Argumentes 'x' bei der Methodenauswahl für Funktion 'first': object 'B' not found

可能的解决方案:

library(tidyverse)

df <- tibble(id = c("one", "two", "three"),
             A = c(1,2,3), 
             B = c(4,5,6))

df %>% 
  group_by(id) %>%
  slice(rep(1,2)) %>% mutate(A = if_else(row_number() > 1, first(df$B), A)) %>% 
  ungroup

#> # A tibble: 6 × 3
#>   id        A     B
#>   <chr> <dbl> <dbl>
#> 1 one       1     4
#> 2 one       4     4
#> 3 three     3     6
#> 4 three     4     6
#> 5 two       2     5
#> 6 two       4     5
library(tidyverse)

df <- tibble(id = c("one", "two", "three"),
             A = c(1,2,3), 
             B = c(4,5,6))

df %>% 
    group_by(id) %>% 
    summarise(add_row(cur_data(), A = 4, B = first(cur_data()$B)))
#> `summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
#> # A tibble: 6 × 3
#> # Groups:   id [3]
#>   id        A     B
#>   <chr> <dbl> <dbl>
#> 1 one       1     4
#> 2 one       4     4
#> 3 three     3     6
#> 4 three     4     6
#> 5 two       2     5
#> 6 two       4     5

或者

df %>% 
    group_by(id) %>% 
    group_split() %>% 
    map_dfr(~ add_row(.,id = first(.$id),  A = 4, B = first(.$B)))
#> # A tibble: 6 × 3
#>   id        A     B
#>   <chr> <dbl> <dbl>
#> 1 one       1     4
#> 2 one       4     4
#> 3 three     3     6
#> 4 three     4     6
#> 5 two       2     5
#> 6 two       4     5

reprex package (v2.0.1)

创建于 2022-01-02

也许这是一个选择

library(dplyr)

df %>% 
  group_by(id) %>%
  summarise( A=c(A,4), B=c(B,first(B)) ) %>% 
  ungroup
`summarise()` has grouped output by 'id'. You can override using the `.groups` argument.
# A tibble: 6 x 3
  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     6
5 two       2     5
6 two       4     5

根据函数group_modify的说明,如果使用公式,必须使用“..x来引用[=14行的子集=] 对于给定的组;"这就是您在 add_row 函数中使用 .x 的原因。为了完全一致,您还必须在 first 函数中执行此操作。

df %>% 
  group_by(id) %>% 
  group_modify(~ add_row(A=4, B=first(.x$B), .x))

# A tibble: 6 x 3
# Groups:   id [3]
  id        A     B
  <chr> <dbl> <dbl>
1 one       1     4
2 one       4     4
3 three     3     6
4 three     4     6
5 two       2     5
6 two       4     5

使用 first(.$B)first(df$B) 将提供相同的结果。