是否有任何简单的方法可以通过RCpp中的两个(或多个或一个)列来订购DataFrame?
网上有很多排序算法,或者我可以使用std::sortDataFrame的包装器,但我想知道RCpp或RCppArmadillo中是否有可用的东西?
我需要将此排序/排序作为另一个函数的一部分
DataFrame myFunc(DataFrame myDF, NumericVector x) {
//// some code here
DataFrame myDFsorted = sort (myDF, someColName1, someColName2) // how to sort??
//// some code here
}
Run Code Online (Sandbox Code Playgroud)
我想避免order在RCpp中访问R的功能(为了保持RCpp代码的速度).
非常感谢
Rom*_*ois 12
困难在于数据帧是一组可能具有不同类型的向量; 我们需要一种方法来独立于这些类型(整数,字符......)对它们进行排序.在dplyr,我们开发了所谓的矢量访问者.对于这个特殊问题,我们需要的是一组OrderVisitor,它展示了以下界面:
class OrderVisitor {
public:
virtual ~OrderVisitor(){}
/** are the elements at indices i and j equal */
virtual bool equal(int i, int j) const = 0 ;
/** is the i element less than the j element */
virtual bool before( int i, int j) const = 0 ;
virtual SEXP get() = 0 ;
} ;
Run Code Online (Sandbox Code Playgroud)
然后,dplyr具有OrderVisitor我们在此文件中支持的所有类型的实现,并且我们有一个调度函数order_visitor,它OrderVisitor*从一个向量中生成一个.
有了这个,我们可以将一组矢量访问者存储到一个std::vector<OrderVisitor*>; 该OrderVisitors有一个构造采取DataFrame和CharacterVector我们要使用的排序向量的名字.
OrderVisitors o(data, names ) ;
Run Code Online (Sandbox Code Playgroud)
然后我们可以使用基本上执行词典排序的OrderVisitors.apply方法:
IntegerVector index = o.apply() ;
Run Code Online (Sandbox Code Playgroud)
该apply方法通过简单地初始化a IntegerVector,0..n然后std::sort根据访问者来实现.
inline Rcpp::IntegerVector OrderVisitors::apply() const {
IntegerVector x = seq(0, nrows -1 ) ;
std::sort( x.begin(), x.end(), OrderVisitors_Compare(*this) ) ;
return x ;
}
Run Code Online (Sandbox Code Playgroud)
这里的相关内容是OrderVisitors_Compare类如何实现operator()(int,int):
inline bool operator()(int i, int j) const {
if( i == j ) return false ;
for( int k=0; k<n; k++)
if( ! obj.visitors[k]->equal(i,j) )
return obj.visitors[k]->before(i, j ) ;
return i < j ;
}
Run Code Online (Sandbox Code Playgroud)
所以在这一点index给我们的排序数据的整数索引值,我们只需要创建一个新DataFrame的data由子集划分data与这些指标.为此我们有另一种访问者,封装在DataFrameVisitors课堂上.我们先创建一个DataFrameVisitors:
DataFrameVisitors visitors( data ) ;
Run Code Online (Sandbox Code Playgroud)
这封装了一个std::vector<VectorVisitor*>.这些中的每一个都VectorVisitor*知道如何使用整数向量索引来子集自身.这用于DataFrameVisitors.subset:
template <typename Container>
DataFrame subset( const Container& index, const CharacterVector& classes ) const {
List out(nvisitors);
for( int k=0; k<nvisitors; k++){
out[k] = get(k)->subset(index) ;
}
structure( out, Rf_length(out[0]) , classes) ;
return (SEXP)out ;
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,这里有一个简单的函数,使用在dplyr中开发的工具:
#include <dplyr.h>
// [[Rcpp::depends(dplyr)]]
using namespace Rcpp ;
using namespace dplyr ;
// [[Rcpp::export]]
DataFrame myFunc(DataFrame data, CharacterVector names) {
OrderVisitors o(data, names ) ;
IntegerVector index = o.apply() ;
DataFrameVisitors visitors( data ) ;
DataFrame res = visitors.subset(index, "data.frame" ) ;
return res ;
}
Run Code Online (Sandbox Code Playgroud)
因为 adata.frame实际上是 C++ 中的列列表,所以您必须在给定新排序索引的情况下单独对所有列重新排序。这与[.., ..]R 中的索引工作方式不同data.frame。
例如,请参阅这篇关于对向量进行排序的 Rcpp Gallery 文章以获取一些指针。您可能必须提供要使用的新排序索引,之后这只是一个索引问题 - 画廊上也有一些帖子。
这篇文章可能会帮助您开始创建索引;bytes.com 的这篇文章讨论了同样的想法。
编辑:犰狳具有创建重新排列列所需的索引的功能。 这仅涵盖一列的情况,并且仅限于数字列,但这是一个开始。sort_index()stable_sort_index()
| 归档时间: |
|
| 查看次数: |
1253 次 |
| 最近记录: |