Если еще не слишком поздно, я могу предложить следующее решение.
Сначала , загрузите библиотеку и сгенерируйте набор данных (конечно, в вашем случае нет необходимости генерировать набор данных ):
library(data.table)
# Generate dataset ...
df = data.table(Simulation = sample(1:4, 60, replace = TRUE),
Scenario.ID = sample(1:5, 60, replace = TRUE),
Target.ID = sample(1:2, 60, replace = TRUE))
# ... and sort it
df = df[order(Simulation, Scenario.ID, Target.ID)]
Секунда , задайте коэффициент уменьшения. В этом примере я использую n = 3, в вашем случае это будет n = 5 или любое другое число, соответствующее цели.
n = 3
Третий , определите число строк, которые будут взяты из каждой комбинации сценария и цели. Я округлять числа; они должны быть целыми числами. Если округленное число равно нулю, то в качестве выборки берется 1, чтобы сохранить представление каждой комбинации сценария ios и целей.
group.sample = df[, .N, by = .(Scenario.ID, Target.ID)][, pmax(round(N/n), 1)]
group.sample
[1] 1 2 2 2 2 2 3 2 3 1
Четвертый , отметьте записи как взят в образец (спасибо этот ответ). Я использую set.seed, чтобы сделать пример воспроизводимым. Выбор является случайным.
set.seed(1)
df[, Sample := 1:.N %in% sample(.N, min(.N, group.sample[.GRP])), by = .(Scenario.ID, Target.ID)]
head(df[order(Simulation, Scenario.ID, Target.ID)])
Simulation Scenario.ID Target.ID Sample
1: 1 1 1 FALSE
2: 1 1 1 TRUE
3: 1 1 2 FALSE
4: 1 2 1 FALSE
5: 1 2 2 FALSE
6: 1 3 1 FALSE
Пятый , сравните исходную пропорцию сценария и целевой комбинации с выбранной. Пропорции округляются до двух цифр после запятой.
df[, .(Original = round(.N/ nrow(df), 2),
Sampled = round(length(Sample[Sample == TRUE])/df[Sample == TRUE, .N], 2)),
by = .(Scenario.ID, Target.ID)]
Scenario.ID Target.ID Original Sampled
1: 1 1 0.07 0.05
2: 1 2 0.10 0.10
3: 2 1 0.10 0.10
4: 2 2 0.08 0.10
5: 3 1 0.12 0.10
6: 4 1 0.08 0.10
7: 4 2 0.15 0.15
8: 5 1 0.08 0.10
9: 3 2 0.17 0.15
10: 5 2 0.05 0.05