В этом посте обсуждается процедура выборки с разным процентным соотношением по группам.
Но что, если вы просто хотите семплировать, скажем, 50% без замены по группам? А если вы хотите отобрать 50% с заменой по группам?
С dplyr у вас есть sample_frac
для этого. А как насчет data.table?
Вы можете использовать sample
с .N
, чтобы получить пропорцию. Вы можете использовать replace = TRUE
для выборки с заменой (по умолчанию FALSE
):
DT = data.table(a = sample(1:2), b = sample(1:1000,20))
DT[, .SD[sample(.N, floor(.5 * .N))], by = a]
# a b
# 1: 2 552
# 2: 2 246
# 3: 2 979
# 4: 2 611
# 5: 2 469
# 6: 1 703
# 7: 1 909
# 8: 1 274
# 9: 1 279
# 10: 1 316
Более быстрая альтернатива (взято из @akrun):
DT[DT[, .I[sample(.N, floor(0.5 * .N))], by = a]$V1]
Я буду очень сильно полагаться на эту функцию... так что подумайте о десятках тысяч групповых передискретизаций в симуляциях.
Если групповой порядок data.table
для выборки остается стабильным на протяжении всего моделирования, предварительный расчет индексов более чем удваивает скорость для тысяч повторений.
library(data.table)
dt <- data.table(A = sample(1:10, 1e3, 1), B = sample(1000))
system.time(for (i in 1:1e4) dt[dt[, .I[sample(.N, .N%/%2)], A][[2]]])
#> user system elapsed
#> 4.83 0.23 5.06
system.time({
idx <- dt[,.(.(.I)), A][[2]]
for (i in 1:1e4) dt[unlist(lapply(idx, function(x) sample(x, length(x)%/%2)))]
})
#> user system elapsed
#> 1.78 0.13 1.90
Это процент по группам? @jblood94
Это будет 50% по группе. Чтобы взять пробу, например, со скоростью 40%, измените length(x)%/%2
на floor(length(x)*0.4)
.
Это оказалось примерно в 2,5 раза быстрее моей реализации dplyr::sample_frac. Так что большое спасибо.
Это на самом деле выдает ошибку для меня сейчас: i is invalid type (matrix). Perhaps in future a 2 column matrix could return a list of elements of DT (in the spirit of A[B] in FAQ 2.14).
Хотя, не во всех случаях. Не уверен, почему.
Попробуйте использовать lapply
вместо sapply
.
Можно ли сделать какие-либо оптимизации, чтобы избежать или улучшить .SD? Например: stackoverflow.com/questions/15273491/…