Как мне оптимизировать код dplyr по группам, если все вычисления одинаковы

У меня есть следующий фрейм данных, который является подмножеством гораздо большего, содержащего более 3 миллионов строк.

df <- data.frame(Group = c(1,1,1,2,2,3,3,3,2,2,4,4,1,4,1,3,1,3,2,4,2,1,3,2,4),
              SubGroup = c("A","A","C","B","C","A","B","C","C","A","B","C","C","A","B","C","A","A","B","A","C","C","B","B","C"),
              Type = c("Z","Y","Z","X","X","Y","Z","X","Z","Y","Y","Y","X","Y","Z","X","X","Z","Y","X","Z","Z","Y","X","Y"),
              Value = c(4,7,2,8,4,6,1,8,3,6,3,6,3,5,6,7,3,2,7,4,9,4,7,8,1),
              Dup = c(1,1,0,0,0,1,0,1,1,0,1,0,0,1,0,1,0,1,0,1,1,0,1,1,1))

Для каждой группы есть пять разных формул, которые я хочу рассчитать. 1) Сумма значений по подгруппе 2) Сумма значений по подгруппам и дубликатам 3) Сумма значений по подгруппам и типам Z 4) Сумма значений по подгруппам и типам Y 5) Сумма значений по подгруппам и типам Икс

Вот код, который у меня сейчас есть, используя dplyr:

result <- df %>%
 group_by(Group) %>%
 summarise(SubGroup.A.Total = sum(Value[SubGroup=="A"]),
        SubGroup.A.Dup = sum(Value[SubGroup=="A" & Dup==1]),
        SubGroup.A.TypeZ = sum(Value[SubGroup=="A" & Type=="Z"]),
        SubGroup.A.TypeY = sum(Value[SubGroup=="A" & Type=="Y"]),
        SubGroup.A.TypeX = sum(Value[SubGroup=="A" & Type=="X"]),
        SubGroup.B.Total = sum(Value[SubGroup=="B"]),
        SubGroup.B.Dup = sum(Value[SubGroup=="B" & Dup==1]),
        SubGroup.B.TypeZ = sum(Value[SubGroup=="B" & Type=="Z"]),
        SubGroup.B.TypeY = sum(Value[SubGroup=="B" & Type=="Y"]),
        SubGroup.B.TypeX = sum(Value[SubGroup=="B" & Type=="X"]),
        SubGroup.C.Total = sum(Value[SubGroup=="C"]),
        SubGroup.C.Dup = sum(Value[SubGroup=="C" & Dup==1]),
        SubGroup.C.TypeZ = sum(Value[SubGroup=="C" & Type=="Z"]),
        SubGroup.C.TypeY = sum(Value[SubGroup=="C" & Type=="Y"]),
        SubGroup.C.TypeX = sum(Value[SubGroup=="C" & Type=="X"]))

Тем не менее, я действительно хочу знать, есть ли более эффективный способ сделать это, как с точки зрения времени выполнения, так и с точки зрения количества строк? Поскольку я, по сути, зацикливаю те же пять формул по SubGroup, я думаю, что есть гораздо более простой способ написать это.


person Dfeld    schedule 01.08.2019    source источник


Ответы (2)


В этом ответе используется pivot_wider, который пока доступен только в версии tidyr для разработчиков.

Вы группируете по SubGroup все переменные, которые хотите рассчитать, поэтому стоит добавить это в group_by. Для некоторых переменных вы также группируете по Type, поэтому я думаю, вы могли бы сделать отдельную группировку по Group, SubGroup, Type и снова соединить эти переменные, но неясно, стоит ли это того.

Придерживаясь только group_by(Group, SubGroup), вы можете сделать:

df %>%
    group_by(Group, SubGroup) %>%
    summarize(
        Total = sum(Value),
        Dup = sum(Value[Dup == 1]),
        X = sum(Value[Type == "X"]),
        Y = sum(Value[Type == "Y"]),
        Z = sum(Value[Type == "Z"])
    ) %>%
    pivot_wider(
        names_from = SubGroup,
        values_from = c(-Group, -SubGroup)
    )
person Marius    schedule 01.08.2019

Подобно ответу @Marius:

do.call(
  rbind,
  by(df, list(df$Group, df$SubGroup), FUN = function(x) {
    within(x, {
      value_sum <- sum(Value)
      value_sum_dup1 <- sum(Value[Dup == 1])
      value_sum_dup0 <- sum(Value[Dup == 0])
      value_z <- sum(Value[Type == "Z"])
      value_y <- sum(Value[Type == "Y"])
      value_x <- sum(Value[Type == "Z"])
    })[1, ]
  })
)
person Pablo Rod    schedule 01.08.2019