[英]Using rmultinom with Rcpp
我想在c ++代码中使用R函数rmultinom与Rcpp一起使用。 我得到一个关于参数不足的错误 - 我不熟悉这些论点应该是什么,因为他们不同意R中函数使用的参数。我也没有运气使用“:: Rf_foo”从Rcpp代码访问R函数的语法。
下面是我的代码的简化版本(是的,我正在编写一个gibbs采样器)。
#include <Rcpp.h>
using namespace Rcpp;
// C++ implementation of the R which() function.
int whichC(NumericVector x, double val) {
int ind = -1;
int n = x.size();
for (int i = 0; i < n; ++i) {
if (x[i] == val) {
if (ind == -1) {
ind = i;
} else {
throw std::invalid_argument( "value appears multiple times." );
}
} // end if
} // end for
if (ind != -1) {
return ind;
} else {
throw std::invalid_argument( "value doesn't appear here!" );
return -1;
}
}
// [[Rcpp::export]]
int multSample(double p1, double p2, double p3) {
NumericVector params(3);
params(0) = p1;
params(1) = p2;
params(2) = p3;
// HERE'S THE PROBLEM.
RObject sampled = rmultinom(1, 1, params);
int out = whichC(as<NumericVector>(sampled), 1);
return out;
}
我是c ++的新手,所以我意识到很多这样的代码可能都是高效且低效的。 我愿意接受有关如何改进我的c ++代码的建议,但我的首要任务是听取rmultinom业务。 谢谢!
顺便说一下,我为这个线程的相似性道歉,但是
以下是user95215修改的答案,以便编译,另一个版本更多的是Rcpp样式:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector oneMultinomC(NumericVector probs) {
int k = probs.size();
SEXP ans;
PROTECT(ans = Rf_allocVector(INTSXP, k));
probs = Rf_coerceVector(probs, REALSXP);
rmultinom(1, REAL(probs), k, &INTEGER(ans)[0]);
UNPROTECT(1);
return(ans);
}
// [[Rcpp::export]]
IntegerVector oneMultinomCalt(NumericVector probs) {
int k = probs.size();
IntegerVector ans(k);
rmultinom(1, probs.begin(), k, ans.begin());
return(ans);
}
如果我尝试编译您的代码,我会收到编译器错误:
> Rcpp::sourceCpp('~/scratch/multSample.cpp')
multSample.cpp:33:21: error: no matching function for call to 'rmultinom'
RObject sampled = rmultinom(1, 1, params);
^~~~~~~~~
/Library/Frameworks/R.framework/Resources/include/Rmath.h:449:6: note: candidate function not viable: requires 4 arguments, but 3 were provided
void rmultinom(int, double*, int, int*);
^
1 error generated.
如它所示,您没有正确指定参数。 请注意,与其他函数相比, rmultinom
接口有点笨拙:它填充*rn
指向的内存,而不是返回一个新对象(具有自己新分配的内存)。
如果您查看R源代码,您将看到界面,并且您可以看到它在此处使用的示例(事实上, stats
一个包装函数,可以执行更多参数检查等等)。 但请注意它在这里是如何使用的:
rmultinom(size, REAL(prob), k, &INTEGER(ans)[ik]);
换句话说,它的填充INTSXP
称为ans
通过传递到该内存的该地址rmultinom
功能。
因此,如果你想使用Rcpp
这个函数,你将不得不做类似的事情 - 但也许这应该采用类似的糖矢量化处理来避免界面的丑陋。
您可以尝试做类似的事情:
IntegerMatrix sampled(nrow, ncol);
rmultinom(1, 1, params, sampled.begin());
或者那种效果。
Kevin提供的示例和链接使我找到了有效的答案。 有一些类型的争论。 我编写了一个函数,允许您从多项分布中采样一个向量。 代码如下。
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector oneMultinomC(NumericVector probs) {
int k = probs.size();
SEXP ans;
PROTECT(ans = RF_allocVector(INTSXP, k));
probs = RF_coerceVector(probs, REALSXP);
rmultinom(1, REAL(probs), k, &INTEGER(ans)[0]);
UNPROTECT(1);
return ans;
}
我不明白这里发生了一半的事情。 特别是,我不明白'rmultinom'的第四个论点。 我知道它是指向存储输出的存储位置的指针,但我不理解'[0]'位。 尽管如此,它仍然有效。 Gibbs取样,男孩和女孩。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.