В data.table есть функция для этого:
library(data.table)
setDT(df)
res = groupingsets(df, by=c("Effective_Date", "Gender", "Location"),
sets=list(
c("Effective_Date", "Gender"),
c("Effective_Date", "Gender", "Location")
), j = .(n = sum(n), freq = mean(freq))
)[order(Effective_Date, Gender, Location, na.last=TRUE)]
Effective_Date Gender Location n freq
1: 2017-01-01 Female India 281 0.3510
2: 2017-01-01 Female US 2446 0.5420
3: 2017-01-01 Female <NA> 2727 0.4465
4: 2017-02-01 Female India 285 0.3490
5: 2017-02-01 Female US 2494 0.5430
6: 2017-02-01 Female <NA> 2779 0.4460
Итак, вы группируете по двум уровням, второй из которых исключает Location
.Если вы хотите, чтобы "All"
показывалось вместо NA
, есть res[is.na(Location), Location := "All"][]
.
(похоже, здесь следует использовать weighted.mean(freq, n)
вместо mean(freq)
... Это также включает счетчик n
для всех строк, так как это кажется странным и утомительно делать иначе.)
Несколько короче:
myby = c("Effective_Date", "Gender", "Location")
groupingsets(df,
j = .(n = sum(n), freq = mean(freq)),
by=myby, sets=list(myby, head(myby, -1))
)[, setorderv(.SD, myby, na.last=TRUE)]