r语言 - 带有列表列的 Rcpp 数据帧返回(Asis 在哪里?



我想在包含列表列的 Rcpp 函数中生成一个数据框。 我已经尝试了几件事,但无法找到可行的解决方案。 以下是我尝试过的 Rcpp c++ 文件:

#include <Rcpp.h>
#include <vector>
using namespace Rcpp;
using namespace std;
// [[Rcpp::export]]
DataFrame makeListColumn() {
vector<RawVector> the_future_list;
the_future_list.push_back(RawVector::create(0, 1, 2));
the_future_list.push_back(RawVector::create(3, 4));
the_future_list.push_back(RawVector::create(5, 6, 7, 8, 9, 10));

vector<int> another_regular_column;
another_regular_column.push_back(42);
another_regular_column.push_back(24);
another_regular_column.push_back(4242);
DataFrame ret = DataFrame::create(Named("another_regular_column") = another_regular_column, Named("thelistcol") = the_future_list);
return ret;
}
/*** R
a = makeListColumn()
dput(a)
*/

由此产生的输出如下:

a = makeListColumn((

结构(list(another_regular_column = c(42L, 24L, 4242L, 42L, 24L, 4242L(, thelistcol.as.raw.c.0x00..0x01..0x02.. = as.raw(c(0x00, 0x01, 0x02, 0x00, 0x01, 0x02((, thelistcol.as.raw.c.0x03..0x04.. = as.raw(c(0x03, 0x04, 0x03, 0x04, 0x03, 0x04((, thelistcol.as.raw.c.0x05..0x06..0x07..0x08..0x09..0x0a.. = as.raw(c(0x05, 0x06, 0x07, 0x08, 0x09, 0x0a(((, class = "data.frame", row.names = c(NA, -6L((

我正在寻找以下内容(在常规 R 脚本中完成(:

what_i_wanted = data.frame(
another_regular_column = c(42, 24, 4242),  
thelistcol = I(list(as.raw(c(0,1,2)), as.raw(c(3, 4)), as.raw(c(5, 6, 7, 8, 9, 10))))
)

这将产生输出:

structure(list(another_regular_column = c(42,

24, 4242(, thelistcol = structure(list( as.raw(c(0x00, 0x01, 0x02((, as.raw(c(0x03, 0x04((, as.raw(c(0x05, 0x06, 0x07, 0x08, 0x09, 0x0a(((, class = "AsIs"((, class = "data.frame", row.names = c(NA, -3L((

R和 Rcpp 方法之间的主要区别在于 R 代码中的I()调用。 如果我删除它,R 代码会生成与 Rcpp 代码相同的结构。 我在 Rcpp 文档中做了一些查找并做了一些谷歌搜索,但空手而归。

有人可以帮助我了解我需要在 Rcpp 中做什么才能让它工作吗?

编辑:

我确实尝试做这样的事情:

List the_list = List::create(the_future_list);
the_list.attr("class") = CharacterVector::create("AsIs");

不幸的是,这导致了以下错误:

makeListColumn(( 中的错误: 无法使用 R 函数进行转换:as.data.frame。

AsIs

未实现。

C++内处理data.framelist列的最佳方法是使用Rcpp::List来处理构造。回想一下,data.frame是强制实施观察计数的list。此外,我们可以修改Rcpp::List对象属性(与std数据结构不同(以包含AsIs标志。

简而言之,这看起来像:

#include <Rcpp.h>
// [[Rcpp::export]]
SEXP makeListColumn() {
// ^ Changed from Rcpp::DataFrame to a general SEXP object. 
// Store inside of an Rcpp List
Rcpp::List the_future_list(3);
the_future_list[0] = Rcpp::RawVector::create(0, 1, 2);
the_future_list[1] = Rcpp::RawVector::create(3, 4);
the_future_list[2] = Rcpp::RawVector::create(5, 6, 7, 8, 9, 10);
// Mark with AsIs
the_future_list.attr("class") = "AsIs";
// Store inside of a regular vector
std::vector<int> another_regular_column;
another_regular_column.push_back(42);
another_regular_column.push_back(24);
another_regular_column.push_back(4242);
// Construct a list 
Rcpp::List ret = Rcpp::List::create(
Rcpp::Named("another_regular_column") = another_regular_column,
Rcpp::Named("thelistcol") = the_future_list);
// Coerce to a data.frame
ret.attr("class") = "data.frame";
ret.attr("row.names") = Rcpp::seq(1, another_regular_column.size());
// Return the data.frame
return ret;
}

最重要的是,请注意,我们放弃了Rcpp::DataFrame类并返回一个SEXP对象。此外,我们通过更改class并将row.names分配给对象来强制Rcpp::ListRcpp::DataFrame

在实践中,代码返回:

a = makeListColumn()
str(a)
# 'data.frame': 3 obs. of  2 variables:
# $ another_regular_column: int  42 24 4242
# $ thelistcol            :List of 3
#  ..$ : raw  00 01 02
#  ..$ : raw  03 04
#  ..$ : raw  05 06 07 08 ...
#  ..- attr(*, "class")= chr "AsIs"

与所需结果相比:

what_i_wanted = data.frame(
another_regular_column = c(42, 24, 4242),  
thelistcol = I(list(as.raw(c(0,1,2)), as.raw(c(3, 4)), as.raw(c(5, 6, 7, 8, 9, 10))))
)
str(what_i_wanted)
# 'data.frame': 3 obs. of  2 variables:
# $ another_regular_column: num  42 24 4242
# $ thelistcol            :List of 3
#  ..$ : raw  00 01 02
#  ..$ : raw  03 04
#  ..$ : raw  05 06 07 08 ...
#  ..- attr(*, "class")= chr "AsIs"
all.equal(a, what_i_wanted)
# [1] TRUE

最新更新