Сведение и промежуточные итоги являются распространенными вспомогательными шагами в электронных таблицах и SQL.
Предположим, что таблица данных с полями date, myCategory, revenue. Предположим, вы хотите узнать долю дневной выручки от всей выручки и долю дневной выручки в разных подгруппах, чтобы
b[,{
#First auxiliary variable of all revenue
totalRev = sum(revenue) #SUBGROUP OF ALL REV
#Second auxiliary variable of revenue by date, syntax wrong! How to do this?
{totalRev_date=sum(revenue), by=list(date)} #DIFFERENT SUBGROUP, by DATE's rev
#Within the subgroup by date and myCategory, we will use 1st&2nd auxiliary vars
.SD[,.(Revenue_prop_of_TOT=revenue/totalRev,
,Revenue_prop_of_DAY=revenue/totalRev_date) ,by=list(myCategory,date)]
},]
где нам нужно вычислить вспомогательные суммы, весь доход за конкретный день и весь доход за всю историю.
Конечный результат должен выглядеть так:
date myCategory Revenue_prop_of_TOT Revenue_prop_of_DAY
2019-01-01 Cat1 0.002 0.2
...
где вы видите, что вспомогательные переменные являются только вспомогательными функциями.





Надеюсь, я правильно понимаю, что вы имеете в виду, но, пожалуйста, дайте мне знать в комментариях, если вам нужен другой результат.
b = data.table(date = rep(seq.Date(Sys.Date()-99, Sys.Date(), "days"), each=2),
myCategory = c("a", "b"),
revenue = rnorm(100, 200))
# global total, just create a constant
totalRev = b[, sum(revenue)]
# Total revenue at myCategory and date level / total Revenue
b[, Revenue_prop_of_TOT:=sum(revenue)/totalRev, by=.(myCategory, date)]
# you can calculate totalRev_date independently
b[, totalRev_date:=sum(revenue), by=date]
# If these are all the columns you have you don't need the sum(revenue) and by calls
b[, Revenue_prop_of_DAY:=sum(revenue)/totalRev_date, by=.(myCategory, date)]
Наконец, я бы обернул его в функцию.
revenue_total <- function(b){
totalRev = b[, sum(revenue)]
b[, Revenue_prop_of_TOT:=sum(revenue)/totalRev, by=.(myCategory, date)]
b[, totalRev_date:=sum(revenue), by=date]
b[, Revenue_prop_of_DAY:=sum(revenue)/totalRev_date, by=.(myCategory, date)]
b
}
b = revenue_total(b)
Другой вариант использования data.table::cube:
cb <- cube(DT, sum(value), by=c("date","category"), id=TRUE)
cb[grouping==0L, .(date, category,
PropByDate = V1 / cb[grouping==1L][.SD, on = "date", x.V1],
PropByCategory = V1 / cb[grouping==2L][.SD, on = "category", x.V1],
PropByTotal = V1 / cb[grouping==3L, V1]
)]
выход:
date category PropByDate PropByCategory PropByTotal
1: 1 1 0.3333333 0.2500000 0.1
2: 1 2 0.6666667 0.3333333 0.2
3: 2 1 0.4285714 0.7500000 0.3
4: 2 2 0.5714286 0.6666667 0.4
данные:
DT <- data.table(date=c(1, 1, 2, 2), category=c(1, 2, 1, 2), value=1:4)
# date category value
#1: 1 1 1
#2: 1 2 2
#3: 2 1 3
#4: 2 2 4
на самом деле он исходит из sql, где многие агрегаты предварительно обрабатываются для ускорения последующего анализа. я вижу, что ваша проблема заключается в том, что вы выполняете много агрегации, и куб пришел на ум
Я не знал о кубе, подробнее здесь. Кажется, это полезно, если вы хотите воспроизвести сводные таблицы Excel, добавить промежуточные итоги и т. д.
Куб фантастический, а еще groupingsets есть на что посмотреть. Если я правильно помню, куб можно реализовать с помощью groupingsets, поэтому он немного более общий для поворота в R. +1 за поиск этого замечательного инструмента.
@hhh вы правильно помните, взгляните на data.table:::cube.data.table
в чем преимущество data.table::cube? Это описание
"Calculate aggregates at various levels of groupings producing multiple (sub-)totals. Reflects SQLs GROUPING SETS operations..