如何使用 Rcpp 将 R 对象交给 C++?
How to hand R objects to C++ using Rcpp?
如何使用 Rcpp 将 R 对象传递给 C++?
嘿,我是 Rcpp 的新手,遇到以下问题(这可能非常简单,但我无法弄清楚)。我首先在 R 中创建一个列表、向量和一个数据框。我想将这些 R 对象传递给 C++ 以修改列表,然后 return 修改后的列表再次返回 R 以供进一步分析。
我在Rstudio中做了一个cpp文件的例子:
#include <Rcpp.h>
using namespace Rcpp;
/*** R
mylist <- list(mat1 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat2 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat3 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat4 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))))
myvector1 <- c(seq(8,10,1))
myvector2 <- c(seq(101,103,1))
mydataframe <- data.frame(Col1 = c('id3','id4','id5'), Col2 = seq(21,23,1), Col3 = as.factor(c('blue','green','black')))
*/
// [[Rcpp::export]]
// Some code modifying mylist with myvector1, myvector2 and mydataframe and returning the modified list again to R
// Let's say Col2 of mat1 of mylist shall be multiplied with myvector1 and Col 2 of mat2 with myvector2.
// Col2 of mat4 shall be divided by Col2 of mydataframe
// And then the modified mylist should be returned
}
/*** R
# Some analysis with the new modified list generated in the C++ code
summary(mylist$mat2$Col2)
*/
我怎样才能让这样的操作正常工作(实际上我的列表要大得多)?还是使用带有 cxxfunction 函数的 Rscript 更好?感谢您的帮助!
您的问题似乎是如何使用 Rcpp 实际地 结合 R 和 C++。我看到了几种方法。选择哪一个取决于代码量、您进行类似分析的频率、您将来必须返回此特定分析的可能性有多大等等。最好自己尝试一下,这样您就可以形成自己的启发式,何时选择哪个。
单个文件
C++ 加 R
如果 C++ 比 R 多,那么使用一个带有特殊 R 注释的 cpp
是很有用的。一般结构:
#include <Rcpp.h>
// [[Rcpp::export]]
void foo(Rcpp::List l, Rcpp::NumericVector v1, Rcpp::NumericVector v2, Rcpp::DataFrame df) {
Rcpp::List mat2 = l["mat2"];
Rcpp::NumericVector Col2 = mat2["Col2"];
Col2(0) = 10;
}
/*** R
mylist <- list(mat1 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat2 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat3 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat4 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))))
myvector1 <- c(seq(8,10,1))
myvector2 <- c(seq(101,103,1))
mydataframe <- data.frame(Col1 = c('id3','id4','id5'), Col2 = seq(21,23,1), Col3 = as.factor(c('blue','green','black')))
foo(mylist, myvector1, myvector2, mydataframe)
summary(mylist$mat2$Col2)
*/
这与您所拥有的相似,但只有一个 R 注释。您需要调用 Rcpp::sourceCpp("<file>")
来编译它并执行 R 注释中的代码。在 RStudio 中,您可以为此使用 "Source"。
请注意,在上面的示例中,列表是通过引用更改的,这可能很危险,因为 R 遵循写时复制策略。对于大型列表,这当然很昂贵,这可能就是您正在寻找 C++ 解决方案的原因。
R 加 C++
如果只有很少的 C++ 代码,您可以使用 Rcpp:cppFunction("<C++ code>")
。我不会再使用 inline::cxxfunction
了。我很少使用这种方法,因为没有编辑器支持 C++ 代码。
R 降价
R Markdown 允许您使用 r
和 rcpp
块在平等的基础上组合 R 和 C++。如果您想在分析中添加一些散文,这将非常有用。在 RStudio 中,您可以获得对这两种类型块的编辑器支持。然而,有时来自 C++ 编译器的错误消息会被打乱,使它们更难解释。
多个文件
项目
如果代码量增加或数据文件进入,您可能会考虑某种项目结构,例如目录 data
、R
和 src
用于数据文件、具有函数定义的 R 脚本和 C++ 文件。然后,驱动程序文件(R 或 Rmd)将在进行实际分析之前加载数据、source
R 脚本和 sourceCpp
C++ 文件。
R包
一旦你使用了一个项目结构,你也可以去寻找一个包。只需很少的额外工作,您就可以获得几个优势:
- C++代码只需要编译一次
- R 函数立即进行字节编译
- C++ 函数可以很容易地用于并行处理
- 用于集成文档和测试的清晰结构
- ...
请注意,您可以从一个空包和一个 Rmd 文件开始。一开始,您只使用 Rmd 文件。您可以时不时地重构代码,将其部分作为 R 或 C++ 函数移动到包中。
如何使用 Rcpp 将 R 对象传递给 C++?
嘿,我是 Rcpp 的新手,遇到以下问题(这可能非常简单,但我无法弄清楚)。我首先在 R 中创建一个列表、向量和一个数据框。我想将这些 R 对象传递给 C++ 以修改列表,然后 return 修改后的列表再次返回 R 以供进一步分析。
我在Rstudio中做了一个cpp文件的例子:
#include <Rcpp.h>
using namespace Rcpp;
/*** R
mylist <- list(mat1 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat2 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat3 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat4 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))))
myvector1 <- c(seq(8,10,1))
myvector2 <- c(seq(101,103,1))
mydataframe <- data.frame(Col1 = c('id3','id4','id5'), Col2 = seq(21,23,1), Col3 = as.factor(c('blue','green','black')))
*/
// [[Rcpp::export]]
// Some code modifying mylist with myvector1, myvector2 and mydataframe and returning the modified list again to R
// Let's say Col2 of mat1 of mylist shall be multiplied with myvector1 and Col 2 of mat2 with myvector2.
// Col2 of mat4 shall be divided by Col2 of mydataframe
// And then the modified mylist should be returned
}
/*** R
# Some analysis with the new modified list generated in the C++ code
summary(mylist$mat2$Col2)
*/
我怎样才能让这样的操作正常工作(实际上我的列表要大得多)?还是使用带有 cxxfunction 函数的 Rscript 更好?感谢您的帮助!
您的问题似乎是如何使用 Rcpp 实际地 结合 R 和 C++。我看到了几种方法。选择哪一个取决于代码量、您进行类似分析的频率、您将来必须返回此特定分析的可能性有多大等等。最好自己尝试一下,这样您就可以形成自己的启发式,何时选择哪个。
单个文件
C++ 加 R
如果 C++ 比 R 多,那么使用一个带有特殊 R 注释的 cpp
是很有用的。一般结构:
#include <Rcpp.h>
// [[Rcpp::export]]
void foo(Rcpp::List l, Rcpp::NumericVector v1, Rcpp::NumericVector v2, Rcpp::DataFrame df) {
Rcpp::List mat2 = l["mat2"];
Rcpp::NumericVector Col2 = mat2["Col2"];
Col2(0) = 10;
}
/*** R
mylist <- list(mat1 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat2 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat3 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))),
mat4 = data.frame(Col1 = c('id1','id2','id3'), Col2 = c(5,6,7), Col3 = as.factor(c('blue','green','black'))))
myvector1 <- c(seq(8,10,1))
myvector2 <- c(seq(101,103,1))
mydataframe <- data.frame(Col1 = c('id3','id4','id5'), Col2 = seq(21,23,1), Col3 = as.factor(c('blue','green','black')))
foo(mylist, myvector1, myvector2, mydataframe)
summary(mylist$mat2$Col2)
*/
这与您所拥有的相似,但只有一个 R 注释。您需要调用 Rcpp::sourceCpp("<file>")
来编译它并执行 R 注释中的代码。在 RStudio 中,您可以为此使用 "Source"。
请注意,在上面的示例中,列表是通过引用更改的,这可能很危险,因为 R 遵循写时复制策略。对于大型列表,这当然很昂贵,这可能就是您正在寻找 C++ 解决方案的原因。
R 加 C++
如果只有很少的 C++ 代码,您可以使用 Rcpp:cppFunction("<C++ code>")
。我不会再使用 inline::cxxfunction
了。我很少使用这种方法,因为没有编辑器支持 C++ 代码。
R 降价
R Markdown 允许您使用 r
和 rcpp
块在平等的基础上组合 R 和 C++。如果您想在分析中添加一些散文,这将非常有用。在 RStudio 中,您可以获得对这两种类型块的编辑器支持。然而,有时来自 C++ 编译器的错误消息会被打乱,使它们更难解释。
多个文件
项目
如果代码量增加或数据文件进入,您可能会考虑某种项目结构,例如目录 data
、R
和 src
用于数据文件、具有函数定义的 R 脚本和 C++ 文件。然后,驱动程序文件(R 或 Rmd)将在进行实际分析之前加载数据、source
R 脚本和 sourceCpp
C++ 文件。
R包
一旦你使用了一个项目结构,你也可以去寻找一个包。只需很少的额外工作,您就可以获得几个优势:
- C++代码只需要编译一次
- R 函数立即进行字节编译
- C++ 函数可以很容易地用于并行处理
- 用于集成文档和测试的清晰结构
- ...
请注意,您可以从一个空包和一个 Rmd 文件开始。一开始,您只使用 Rmd 文件。您可以时不时地重构代码,将其部分作为 R 或 C++ 函数移动到包中。