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)
如果您要选择一个,1:n您可以使用sampl.int更快的一个。而且applying 速度matrix更快。将两者放入一个函数中psamp速度更快。
所以,试试这个(我添加了dt[, 1:3]这样,一旦添加列就不会失败):
psamp <- function(x) sample.int(n=3, size=1, prob=x)\ndt[, sample :=apply(as.matrix(dt[, 1:3]), 1, psamp)]\nRun Code Online (Sandbox Code Playgroud)\n为了稍微摆脱apply我们可以Vectorize psamp使用的do.call。另外\xe2\x80\x94正如@IRTFM在他的答案\xe2\x80\x94中建议的那样,我们应该使用该.SD符号。
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\')]\nRun Code Online (Sandbox Code Playgroud)\n为了将性能提高一个数量级以上,正如@Henrik在评论中建议的那样,我们可以使用Rcpp. 我稍微调整了这个答案的代码并使用了新的Rcpp::sample,它很好地给出了相同的base::sample结果set.seed。
#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\')] \nRun Code Online (Sandbox Code Playgroud)\n基准测试,每次重复 100k*100 次:
\nUnit: 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 \nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
528 次 |
| 最近记录: |