返回带有列表列的RCPP数据帧(ASIS在哪里?) [英] Rcpp Data Frame Return with a List Column (Where is the AsIs?)
本文介绍了返回带有列表列的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=make ListColumn()
结构(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.name=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),the ListColumn=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.name=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");
这很遗憾地导致了以下错误:
make ListColumn()出错: 无法使用R函数进行转换:as.data.Frame。
推荐答案
AsIs
未实现。
处理C++中data.frame
中的list
列的最佳方法是使用Rcpp::List
来处理构造。回想一下,data.frame
是具有观察计数强制的list
。此外,与std
数据结构不同,我们可以修改Rcpp::List
对象属性以包括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::List
强制为Rcpp::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
这篇关于返回带有列表列的RCPP数据帧(ASIS在哪里?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文