Добавление новой строки в фрейм данных с группировкой и суммированием - PullRequest
0 голосов
/ 05 ноября 2019

Я хочу сгруппировать свой df по трем столбцам и добавить новую строку, которая будет суммой четвертого столбца.

Мои данные выглядят как

fc <- c("F", "F", "E", "E", "TF", "TF")
group_code <- c("Egg_x", "Egg_y", "Egg_x", "Egg_y", "Egg_x", "Egg_y")
id <- c(1, 1, 1, 1, 1, 1)
value <- c(2, 21, 4, 3, 20, 15)

df <-data.frame(cbind(fc, group_code, id, value))

> df
  fc group_code id value
1  F      Egg_x  1     2
2  F      Egg_y  1    21
3  E      Egg_x  1     4
4  E      Egg_y  1     3
5 TF      Egg_x  1    20
6 TF      Egg_y  1    15

В этом примере я хочу создать новую группу, которая будет включать в себя Egg_x и Egg_y, я могу сделать это с помощью df$group <- sub('\\_.*', '', df$group_code),у нас есть

> df
  fc group_code id value main_group
1  F      Egg_x  1     2  Egg
2  F      Egg_y  1    21  Egg
3  E      Egg_x  1     4  Egg
4  E      Egg_y  1     3  Egg
5 TF      Egg_x  1    20  Egg
6 TF      Egg_y  1    15  Egg

Я хочу добавить новую строку для каждого значения столбца fc, по которому я группируюсь по fc, id и main_group и получаю сумму столбца значений.

Мой конечный df должен выглядеть следующим образом:

> df
  fc group_code id value main_group
1  F      Egg_x  1     2  Egg
2  F      Egg_y  1    21  Egg
3  F      Egg    1    23  Egg
4  E      Egg_x  1     4  Egg
5  E      Egg_y  1     3  Egg
6  E      Egg    1     7  Egg
7 TF      Egg_x  1    20  Egg
8 TF      Egg_y  1    15  Egg
9 TF      Egg    1    35  Egg 

В приведенном выше df каждой третьей строке указан элемент value в сумме двух предыдущих элементов.

Спасибо

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Сначала мы создадим отдельный фрейм данных со строками сводки - df_sum:

library(dplyr)
library(forcats)

df <-
  tibble(
    fc         = c("F", "F", "E", "E", "TF", "TF"),
    group_code = c("Egg_x", "Egg_y", "Egg_x", "Egg_y", "Egg_x", "Egg_y"),
    id         = c(1, 1, 1, 1, 1, 1),
    value      = c(2, 21, 4, 3, 20, 15)
  ) %>% 
  mutate(main_group = sub('\\_.*', '', group_code))


df_sum <-
  df %>% 
  group_by(fc, main_group, id) %>% 
  summarise(value =  sum(value)) %>% 
  mutate(group_code = main_group)

df_sum
#> # A tibble: 3 x 5
#> # Groups:   fc, main_group [3]
#>   fc    main_group    id value group_code
#>   <chr> <chr>      <dbl> <dbl> <chr>     
#> 1 E     Egg            1     7 Egg       
#> 2 F     Egg            1    23 Egg       
#> 3 TF    Egg            1    35 Egg

Затем мы свяжем его с исходным df и упорядочим

res <-
  bind_rows(df, df_sum) %>% 
  # fct_inorder to make sure summary rows appear after
  # original rows after sorting
  mutate(group_code = fct_inorder(group_code)) %>% 
  arrange(fc, main_group, id, group_code) %>% 
  mutate()

res
#> # A tibble: 9 x 5
#>   fc    group_code    id value main_group
#>   <chr> <fct>      <dbl> <dbl> <chr>     
#> 1 E     Egg_x          1     4 Egg       
#> 2 E     Egg_y          1     3 Egg       
#> 3 E     Egg            1     7 Egg       
#> 4 F     Egg_x          1     2 Egg       
#> 5 F     Egg_y          1    21 Egg       
#> 6 F     Egg            1    23 Egg       
#> 7 TF    Egg_x          1    20 Egg       
#> 8 TF    Egg_y          1    15 Egg       
#> 9 TF    Egg            1    35 Egg
1 голос
/ 05 ноября 2019

Преобразование вашего фрейма данных в широкий формат, затем создание нового столбца Egg = Egg_x + Egg_y и преобразование обратно в длинный формат

library(tidyverse)

df %>% 
  spread(group_code, value) %>% 
  mutate(Egg = Egg_x + Egg_y) %>% 
  gather(key = "group_code", value, -fc, -id) %>% 
  arrange(fc)
#>   fc id group_code value
#> 1  E  1      Egg_x     4
#> 2  E  1      Egg_y     3
#> 3  E  1        Egg     7
#> 4  F  1      Egg_x     2
#> 5  F  1      Egg_y    21
#> 6  F  1        Egg    23
#> 7 TF  1      Egg_x    20
#> 8 TF  1      Egg_y    15
#> 9 TF  1        Egg    35

Создано в 2019-11-05 пакетом представ. (v0.3.0)

...