用于生成 r x c 列联表的算法的 Rcpp 包装器
Rcpp wrapper for algorithm to generate r x c contingency tables
我正在尝试使用算法的这个 C++ 实现来有效地生成具有固定边距的 r x c 列联表:https://people.sc.fsu.edu/%7Ejburkardt/cpp_src/asa159/asa159.html
我正在使用 Rcpp 并尝试创建一个可以在 R 中使用的函数。我知道在 R 中有一个 C 实现的这个算法。这对我不起作用,因为我需要能够在 Rcpp 中使用此功能。作为一个中间步骤,我只是想包装这个算法并将其导出到 R。看起来很简单,但我一直在努力解决这个问题。
原函数定义如下:
void rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], bool *key,
int *seed, int matrix[], int *ierror )
这是一个link直接算法:https://people.sc.fsu.edu/%7Ejburkardt/cpp_src/asa159/asa159.cpp
我不需要错误处理,也不知道如何处理 void 类型,所以我稍微修改了算法,结果是这样的:
int* rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], bool *key,
int *seed, int matrix[])
我做了几次尝试。这是一个例子。这将编译,但是当我尝试 运行 R 中的函数时,它崩溃了。
#include <Rcpp.h>
#include "asa159.h"
using namespace Rcpp;
//[[Rcpp::export]]
IntegerVector rcont2_cpp(int nrow,
int ncol,
IntegerVector nrowt_r,
IntegerVector ncolt_r,
bool key_r,
int seed_r) {
std::vector<int> nrowt_rr = as< std::vector<int> >(nrowt_r);
std::vector<int> ncolt_rr = as< std::vector<int> >(ncolt_r);
int* nrowt = &nrowt_rr[0];
int* ncolt = &ncolt_rr[0];
int matrix[nrow * ncol];
bool *key = &key_r;
int *seed = &seed_r;
int* out = rcont2(nrow, ncol, nrowt, ncolt, key, seed, matrix);
int len_out = *(&out + 1) - out;
std::vector<int> value_vec(out, out + len_out);
return wrap(value_vec);
}
我想我在这里犯了一些基本错误。提前谢谢有时间看的人。
这实际上是一个很好的问题,我也很幸运地遇到了来自 FSU 的 John Burkardt 的 very comprehensive site 例程。
但没有什么是完全免费的,需要了解 一点 C 和 C++ 的工作原理 才能通过 Rcpp 将此类例程集成到 R 中。我的最终文件版本比 短得多 :我们只是将行总和和列总和发送给它,然后得到所需的矩阵。我们还在底部添加了示例的 R 调用(一个不错的技巧!)
代码
#include <Rcpp.h>
#include <asa159.cpp>
// [[Rcpp::export]]
Rcpp::IntegerMatrix rcont2_cpp(Rcpp::IntegerVector rowsums, Rcpp::IntegerVector colsums) {
int nrow = rowsums.length();
int ncol = colsums.length();
Rcpp::IntegerMatrix matrix(nrow, ncol);
rcont2(nrow, ncol, rowsums.begin(), colsums.begin(), matrix.begin());
return matrix;
}
/*** R
rs <- c(6, 5)
cs <- c(3, 4, 4)
rcont2_cpp(rs, cs)
rcont2_cpp(rs, cs) // different answer as randomized algo
rcont2_cpp(rs, cs) // different answer as randomized algo
*/
输出
这包含三个示例调用。
> sourceCpp("rcont2.cpp")
> rs <- c(6, 5)
> cs <- c(3, 4, 4)
> rcont2_cpp(rs, cs)
[,1] [,2] [,3]
[1,] 3 1 2
[2,] 0 3 2
> rcont2_cpp(rs, cs)
[,1] [,2] [,3]
[1,] 1 3 2
[2,] 2 1 2
> rcont2_cpp(rs, cs)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 2 1
>
与原始版本不同 asa159.cpp
与原来asa159.cpp
的变化很小:我们使用了R自带的RNG,我们简化了调用接口。正如他们所说,通过 Rcpp::stop()
传播错误条件留作练习:)
--- asa159.orig.cpp 2020-01-30 08:20:42.000000000 -0600
+++ asa159.cpp 2022-02-06 19:52:20.999042887 -0600
@@ -428,8 +428,8 @@
}
//****************************************************************************80
-void rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], bool *key,
- int *seed, int matrix[], int *ierror )
+void rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], /*bool *key, */
+ /*int *seed,*/ int matrix[] /*, int *ierror*/ )
//****************************************************************************80
//
@@ -517,6 +517,10 @@
double x;
double y;
+ bool keyflag = false; // added
+ bool *key = &keyflag; // added
+ int ierr = 0; // added
+ int *ierror = &ierr; // added
*ierror = 0;
//
// On user's signal, set up the factorial table.
@@ -638,7 +642,7 @@
//
// Generate a pseudo-random number.
//
- r = r8_uniform_01 ( seed );
+ r = R::runif(0,1); //r8_uniform_01 ( seed );
//
// Compute the conditional expected value of MATRIX(L,M).
//
@@ -740,7 +744,7 @@
break;
}
- r = r8_uniform_01 ( seed );
+ r = R::runif(0,1); // r8_uniform_01 ( seed );
r = sumprb * r;
}
我正在尝试使用算法的这个 C++ 实现来有效地生成具有固定边距的 r x c 列联表:https://people.sc.fsu.edu/%7Ejburkardt/cpp_src/asa159/asa159.html
我正在使用 Rcpp 并尝试创建一个可以在 R 中使用的函数。我知道在 R 中有一个 C 实现的这个算法。这对我不起作用,因为我需要能够在 Rcpp 中使用此功能。作为一个中间步骤,我只是想包装这个算法并将其导出到 R。看起来很简单,但我一直在努力解决这个问题。
原函数定义如下:
void rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], bool *key,
int *seed, int matrix[], int *ierror )
这是一个link直接算法:https://people.sc.fsu.edu/%7Ejburkardt/cpp_src/asa159/asa159.cpp
我不需要错误处理,也不知道如何处理 void 类型,所以我稍微修改了算法,结果是这样的:
int* rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], bool *key,
int *seed, int matrix[])
我做了几次尝试。这是一个例子。这将编译,但是当我尝试 运行 R 中的函数时,它崩溃了。
#include <Rcpp.h>
#include "asa159.h"
using namespace Rcpp;
//[[Rcpp::export]]
IntegerVector rcont2_cpp(int nrow,
int ncol,
IntegerVector nrowt_r,
IntegerVector ncolt_r,
bool key_r,
int seed_r) {
std::vector<int> nrowt_rr = as< std::vector<int> >(nrowt_r);
std::vector<int> ncolt_rr = as< std::vector<int> >(ncolt_r);
int* nrowt = &nrowt_rr[0];
int* ncolt = &ncolt_rr[0];
int matrix[nrow * ncol];
bool *key = &key_r;
int *seed = &seed_r;
int* out = rcont2(nrow, ncol, nrowt, ncolt, key, seed, matrix);
int len_out = *(&out + 1) - out;
std::vector<int> value_vec(out, out + len_out);
return wrap(value_vec);
}
我想我在这里犯了一些基本错误。提前谢谢有时间看的人。
这实际上是一个很好的问题,我也很幸运地遇到了来自 FSU 的 John Burkardt 的 very comprehensive site 例程。
但没有什么是完全免费的,需要了解 一点 C 和 C++ 的工作原理 才能通过 Rcpp 将此类例程集成到 R 中。我的最终文件版本比 短得多 :我们只是将行总和和列总和发送给它,然后得到所需的矩阵。我们还在底部添加了示例的 R 调用(一个不错的技巧!)
代码
#include <Rcpp.h>
#include <asa159.cpp>
// [[Rcpp::export]]
Rcpp::IntegerMatrix rcont2_cpp(Rcpp::IntegerVector rowsums, Rcpp::IntegerVector colsums) {
int nrow = rowsums.length();
int ncol = colsums.length();
Rcpp::IntegerMatrix matrix(nrow, ncol);
rcont2(nrow, ncol, rowsums.begin(), colsums.begin(), matrix.begin());
return matrix;
}
/*** R
rs <- c(6, 5)
cs <- c(3, 4, 4)
rcont2_cpp(rs, cs)
rcont2_cpp(rs, cs) // different answer as randomized algo
rcont2_cpp(rs, cs) // different answer as randomized algo
*/
输出
这包含三个示例调用。
> sourceCpp("rcont2.cpp")
> rs <- c(6, 5)
> cs <- c(3, 4, 4)
> rcont2_cpp(rs, cs)
[,1] [,2] [,3]
[1,] 3 1 2
[2,] 0 3 2
> rcont2_cpp(rs, cs)
[,1] [,2] [,3]
[1,] 1 3 2
[2,] 2 1 2
> rcont2_cpp(rs, cs)
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 2 2 1
>
与原始版本不同 asa159.cpp
与原来asa159.cpp
的变化很小:我们使用了R自带的RNG,我们简化了调用接口。正如他们所说,通过 Rcpp::stop()
传播错误条件留作练习:)
--- asa159.orig.cpp 2020-01-30 08:20:42.000000000 -0600
+++ asa159.cpp 2022-02-06 19:52:20.999042887 -0600
@@ -428,8 +428,8 @@
}
//****************************************************************************80
-void rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], bool *key,
- int *seed, int matrix[], int *ierror )
+void rcont2 ( int nrow, int ncol, int nrowt[], int ncolt[], /*bool *key, */
+ /*int *seed,*/ int matrix[] /*, int *ierror*/ )
//****************************************************************************80
//
@@ -517,6 +517,10 @@
double x;
double y;
+ bool keyflag = false; // added
+ bool *key = &keyflag; // added
+ int ierr = 0; // added
+ int *ierror = &ierr; // added
*ierror = 0;
//
// On user's signal, set up the factorial table.
@@ -638,7 +642,7 @@
//
// Generate a pseudo-random number.
//
- r = r8_uniform_01 ( seed );
+ r = R::runif(0,1); //r8_uniform_01 ( seed );
//
// Compute the conditional expected value of MATRIX(L,M).
//
@@ -740,7 +744,7 @@
break;
}
- r = r8_uniform_01 ( seed );
+ r = R::runif(0,1); // r8_uniform_01 ( seed );
r = sumprb * r;
}