data.table 样本,概率存储在列中

Gre*_*ent 5 random r function data.table rowwise

我有一个数据表,其中存储在列中的离散分布的概率。

例如,dt <- data.table(p1 = c(0.5, 0.25, 0.1), p2 = c(0.25, 0.5, 0.1), p3 = c(0.25, 0.25, 0.8))

我想创建一个新的随机变量列,使用同一行中的概率进行采样。在 data.table 语法中,我想象它的工作方式如下:

dt[, sample := sample(1:3, 1, prob = c(p1, p2, p3))]
Run Code Online (Sandbox Code Playgroud)

如果有一个类似于“pmin”和“pmax”的“psample”函数,那么这将起作用。我能够使用 apply 来完成这项工作,缺点是对于我的真实数据集,这需要比我想要的更长的时间。有没有办法使用 data.table 来完成这项工作?下面给出应用解决方案。

dt[, sample := apply(dt, 1, function(x) sample(1:3, 1, prob = x[c('p1', 'p2', 'p3')]))]
Run Code Online (Sandbox Code Playgroud)

jay*_*.sf 4

如果您要选择一个,1:n您可以使用sampl.int更快的一个。而且applying 速度matrix更快。将两者放入一个函数中psamp速度更快。

\n

所以,试试这个(我添加了dt[, 1:3]这样,一旦添加列就不会失败):

\n
psamp <- function(x) sample.int(n=3, size=1, prob=x)\ndt[, sample :=apply(as.matrix(dt[, 1:3]), 1, psamp)]\n
Run Code Online (Sandbox Code Playgroud)\n

为了稍微摆脱apply我们可以Vectorize psamp使用的do.call。另外\xe2\x80\x94正如@IRTFM在他的答案\xe2\x80\x94中建议的那样,我们应该使用该.SD符号。

\n
psampv <- Vectorize(function(p1, p2, p3) sample.int(n=3, size=1, replace=TRUE, prob=c(p1, p2, p3)))\ndt[, sample := do.call(psampv, .SD), .SDcols=c(\'p1\',\'p2\',\'p3\')]\n
Run Code Online (Sandbox Code Playgroud)\n

为了将性能提高一个数量级以上,正如@Henrik评论中建议的那样,我们可以使用Rcpp. 我稍微调整了这个答案的代码并使用了新的Rcpp::sample,它很好地给出了相同的base::sample结果set.seed

\n
#include <Rcpp.h>\n// [[Rcpp::export]]\nRcpp::IntegerVector sample_matrix1(Rcpp::NumericMatrix x, Rcpp::IntegerVector choice_set) {\n  int n = x.nrow();\n  Rcpp::IntegerVector result(n);\n  for (int i = 0; i < n; ++i) {\n    Rcpp::NumericVector z(x(i, Rcpp::_));\n    result[i] = Rcpp::sample(choice_set, 1, false, z)[0];\n  }\n  return result;\n}\n\nRcpp::sourceCpp("sample_matrix1.cpp")\n\ndt[, sample := sample_matrix1(as.matrix(.SD), 1:3), .SDcols=c(\'p1\',\'p2\',\'p3\')] \n
Run Code Online (Sandbox Code Playgroud)\n

基准测试,每次重复 100k*100 次:

\n
Unit: milliseconds\n          expr        min         lq       mean     median         uq       max neval cld\n      psamp_:= 1195.16708 1259.06558 1327.19581 1311.17878 1349.98905 1515.1187   100   b\n     psamp_.SD 1225.90467 1257.37766 1318.74885 1289.27571 1335.07736 1522.3423   100   b\n     psamp_set 1181.44985 1256.73204 1320.29317 1301.75657 1335.22009 1491.3870   100   b\n psamp_do.call 1181.93117 1251.45863 1316.23306 1285.85710 1337.06674 1476.8023   100   b\n          rcpp   60.73652   67.15291   72.76073   70.47052   73.91629  127.8278   100  a \n
Run Code Online (Sandbox Code Playgroud)\n