Home > OS >  How to add a row to each group and assign values
How to add a row to each group and assign values

Time:01-03

I have this tibble:

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

I want to add a row to each group AND assign values to the new column BUT with a function (here the new row in each group should get A=4 B = the first group value of column B USING first(B)-> desired output:

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

I have tried so far:

If I add a row in a ungrouped tibble with add_row -> this works perfect!

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

If I try to use add_row in a grouped tibble -> this works not:

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.

According to this post Add row in each group using dplyr and add_row() we could use group_modify -> this works great:

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

I want to assign to column B the first value of column B (or it can be any function min(B), max(B) etccc.) -> this does not work:

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

CodePudding user response:

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

Or

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

Created on 2022-01-02 by the reprex package (v2.0.1)

CodePudding user response:

A possible solution:

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
  • Related