R语言中Rcpp基础知识点有哪些

技术R语言中Rcpp基础知识点有哪些这篇文章将为大家详细讲解有关R语言中Rcpp基础知识点有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. 相关配置和说明由于Dirk的书Sea

本文将详细讲解R语言中Rcpp的基本知识点。边肖觉得挺实用的,分享给大家参考。希望你看完这篇文章能有所收获。

1. 相关配置和说明

由于Dirk的著作《Seam R和C与RCPP的集成》出版于13年,RCPP的属性在当时还没有得到CRAN的认可,所以调用和编写Rcpp函数在当时是相当繁琐的。Rcpp Attributes(2016)大大简化了这个过程(“在c和r之间提供一个甚至更直接的连接”),保留了内联函数,并提供了sourceCpp函数来调用外部。cpp文件。换句话说,我们可以在. cpp文件中存储一个C函数,然后通过sourceCpp从R脚本文件中调用这个C函数,就像使用source一样。

例如,在R脚本文件中,我们希望调用名为test.cpp的文件中的函数。我们可以执行以下操作:

图书馆(Rcpp)

sys . setenv(' PKG _ cxflags '='-STD=c11 ')

SourceCpp('test.cpp ')第二行意思是使用C 11的标准编译文件。

在test.cpp文件中,头文件使用Rcpp.h,要输出到R的函数放在//[[RCPP :3360 export]]之后。如果要输出到R的函数需要调用其他C函数,这些需要调用的函数可以放在//[[RCPP :3360 export]]之前。

#includeRcpp.h

使用usingnamespaceRcpp

//[[Rcpp :3360导出]]对于代数计算,Rcpp提供了RcppArmadillo和RcppEigen。如果要使用这个包,需要在函数文件开头注明依赖关系,如//[[RCPP :3360依赖关系(RCPPARMADILO)]],并加载相关头文件:

//[[rcpp :3360 depends(RcppArmadillo)]

# includeRcppArmadillo.h

#includeRcpp.h

使用usingnamespaceRcpp

使用usingnamespacearma

//[[RCPP :3360导出]]C的基础知识可以在这里找到。

00-1010关键词描述int/double/bool/String/auto integer/numeric/boolean/character/auto identificati on(c11)integer vector integer vector numeric vector numeric vector(元素类型为double)complex vector complex vector Not surlogicalvector逻辑向量;r的逻辑变量可以取三个值:真、假、NA;C只有两个布尔值,真或假。如果将r的NA转换为C中的布尔值,则返回True.字符向量字符向量表达式向量表达式类型SRAW向量向量类型整数矩阵向量

>NumericMatrix数值型矩阵(元素的类型为double)LogicalMatrix逻辑型矩阵CharacterMatrix字符矩阵List aka GenericVector列表;lists;类似于R中列表,其元素可以使任何数据类型DataFrame数据框;data frames;在Rcpp内部,数据框其实是通过列表实现的Function函数型Environment环境型;可用于引用R环境中的函数、其他R包中的函数、操作R环境中的变量RObject可以被R识别的类型

注释:

某些R对象可以通过as<Some_RcppObject>(Some_RObject)转化为转化为Rcpp对象。例如:
在R中拟合一个线性模型(其为List),并将其传入C++函数中

>mod=lm(Y~X);
NumericVector resid = as<NumericVector>(mod["residuals"]);
NumericVector fitted = as<NumericVector>(mod["fitted.values"]);

可以通过as<some_STL_vector>(Some_RcppVector),将NumericVector转换为std::vector。例如:

std::vector<double> vec;
vec = as<std::vector<double>>(x);

在函数中,可以用wrap(),将std::vector转换为NumericVector。例如:

arma::vec long_vec(16,arma::fill::randn);
vector<double> long_vec2 = conv_to<vector<double>>::from(long_vec);
NumericVector output = wrap(long_vec2);

在函数返回时,可以使用wrap(),将C++ STL类型转化为R可识别类型。示例见后面输入和输出示例部分。

以上数据类型除了Environment之外(Function不确定),大多可直接作为函数返回值,并被自动转化为R对象。

算数和逻辑运算符号+, -, *, /, ++, --, pow(x,p), <, <=, >, >=, ==, !=。逻辑关系符号&&, ||, !

3. 常用数据类型的建立

//1. Vector
NumericVector V1(n);//创立了一个长度为n的默认初始化的数值型向量V1。
NumericVector V2=NumericVector::create(1, 2, 3); //创立了一个数值型向量V2,并初始化使其含有三个数1,2,3。
LogicalVector V3=LogicalVector::create(true,false,R_NaN);//创立了一个逻辑型变量V3。如果将其转化为R Object,则其含有三个值TRUE, FALSE, NA。
//2. Matrix
NumericMatrix M1(nrow,ncol);//创立了一个nrow*ncol的默认初始化的数值型矩阵。
//3. Multidimensional Array
NumericVector out=NumericVector(Dimension(2,2,3));//创立了一个多维数组。然而我不知道有什么卵用。。
//4. List
NumericMatrix y1(2,2);
NumericVector y2(5);
List L=List::create(Named("y1")=y1,
                    Named("y2")=y2);
//5. DataFrame
NumericVector a=NumericVector::create(1,2,3);
CharacterVector b=CharacterVector::create("a","b","c");
std::vector<std::string> c(3);
c[0]="A";c[1]="B";c[2]="C";
DataFrame DF=DataFrame::create(Named("col1")=a,
                               Named("col2")=b,
                               Named("col3")=c);

4. 常用数据类型元素访问

元素访问 描述
[n] 对于向量类型或者列表,访问第n个元素。对于矩阵类型,首先把矩阵的下一列接到上一列之下,从而构成一个长列向量,并访问第n个元素。不同于R,n从0开始
(i,j) 对于矩阵类型,访问第(i,j)个元素。不同于R,i和j从0开始。不同于向量,此处用圆括号。
List["name1"]/DataFrame["name2"] 访问List中名为name1的元素/访问DataFrame中,名为name2的列。

5. 成员函数

成员函数 描述
X.size() 返回X的长度;适用于向量或者矩阵,如果是矩阵,则先向量化
X.push_back(a) 将a添加进X的末尾;适用于向量
X.push_front(b) 将b添加进X的开头;适用于向量
X.ncol() 返回X的列数
X.nrow() 返回X的行数

6. 语法糖

6.1 算术和逻辑运算符

+, -, *, /, pow(x,p), <, <=, >, >=, ==, !=, !

以上运算符均可向量化。

6.2. 常用函数

is.na()
Produces a logical sugar expression of the same length. Each element of the result expression evaluates to TRUE if the corresponding input is a missing value, or FALSE otherwise.

seq_len()
seq_len( 10 ) will generate an integer vector from 1 to 10 (Note: not from 0 to 9), which is very useful in conjugation withsapply() and lapply().

pmin(a,b) and pmax(a,b)
a and b are two vectors. pmin()(or pmax()) compares the i <script type="math/tex" id="MathJax-Element-1">i</script>th elements of a and b and return the smaller (larger) one.

ifelse()
ifelse( x > y, x+y, x-y ) means if x>y is true, then do the addition; otherwise do the subtraction.

sapply()
sapply applies a C++ function to each element of the given expression to create a new expression. The type of the resulting expression is deduced by the compiler from the result type of the function.

The function can be a free C++ function such as the overload generated by the template function below:

template <typename T>
T square( const T& x){
    return x * x ;
}
sapply( seq_len(10), square<int> ) ;

Alternatively, the function can be a functor whose type has a nested type called result_type

template <typename T>
struct square : std::unary_function<T,T> {
    T operator()(const T& x){
    return x * x ;
    }
}
sapply( seq_len(10), square<int>() ) ;

lappy()
lapply is similar to sapply except that the result is allways an list expression (an expression of type VECSXP).

sign()

其他函数

  • 数学函数: abs(), acos(), asin(), atan(), beta(), ceil(), ceiling(), choose(), cos(), cosh(), digamma(), exp(), expm1(), factorial(), floor(), gamma(), lbeta(), lchoose(), lfactorial(), lgamma(), log(), log10(), log1p(), pentagamma(), psigamma(), round(), signif(), sin(), sinh(), sqrt(), tan(), tanh(), tetragamma(), trigamma(), trunc().

  • 汇总函数: mean(), min(), max(), sum(), sd(), and (for vectors) var()

  • 返回向量的汇总函数: cumsum(), diff(), pmin(), and pmax()

  • 查找函数: match(), self_match(), which_max(), which_min()

  • 重复值处理函数: duplicated(), unique()

7. STL

Rcpp可以使用C++的标准模板库STL中的数据结构和算法。Rcpp也可以使用Boost中的数据结构和算法。

7.1. 迭代器

此处仅仅以一个例子代替,详细参见C++ Primer,或者此处。

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
double sum3(NumericVector x) {
  double total = 0;
  NumericVector::iterator it;
  for(it = x.begin(); it != x.end(); ++it) {
    total += *it;
  }
  return total;
}

7.2. 算法

头文件<algorithm>中提供了许多的算法(可以和迭代器共用),具体可以参见此处。

For example, we could write a basic Rcpp version of findInterval() that takes two arguments a vector of values and a vector of breaks, and locates the bin that each x falls into.

#include <algorithm>
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
IntegerVector findInterval2(NumericVector x, NumericVector breaks) {
  IntegerVector out(x.size());
  NumericVector::iterator it, pos;
  IntegerVector::iterator out_it;
  for(it = x.begin(), out_it = out.begin(); it != x.end(); 
      ++it, ++out_it) {
    pos = std::upper_bound(breaks.begin(), breaks.end(), *it);
    *out_it = std::distance(breaks.begin(), pos);
  }
  return out;
}

7.3. 数据结构

STL所提供的数据结构也是可以使用的,Rcpp知道如何将STL的数据结构转换成R的数据结构,所以可以从函数中直接返回他们,而不需要自己进行转换。
具体请参考此处。

7.3.1. Vectors

详细信息请参见处此

创建
vector<int>, vector<bool>, vector<double>, vector<String>

元素访问
利用标准的[]符号访问元素

元素增加
利用.push_back()增加元素。

存储空间分配
如果事先知道向量长度,可用.reserve()分配足够的存储空间。

例子:

 The following code implements run length encoding (rle()). It produces two vectors of output: a vector of values, and a vector lengths giving how many times each element is repeated. It works by looping through the input vector x comparing each value to the previous: if it's the same, then it increments the last value in lengths; if it's different, it adds the value to the end of values, and sets the corresponding length to 1.

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
List rleC(NumericVector x) {
  std::vector<int> lengths;
  std::vector<double> values;
  // Initialise first value
  int i = 0;
  double prev = x[0];
  values.push_back(prev);
  lengths.push_back(1);
  NumericVector::iterator it;
  for(it = x.begin() + 1; it != x.end(); ++it) {
    if (prev == *it) {
      lengths[i]++;
    } else {
      values.push_back(*it);
      lengths.push_back(1);
      i++;
      prev = *it;
    }
  }
  return List::create(
    _["lengths"] = lengths, 
    _["values"] = values
  );
}
7.3.2. Sets

参见链接1,链接2和链接3。

STL中的集合std::set不允许元素重复,而std::multiset允许元素重复。集合对于检测重复和确定不重复的元素具有重要意义((like unique, duplicated, or in))。

Ordered set: std::setstd::multiset

Unordered set: std::unordered_set
一般而言unordered set比较快,因为它们使用的是hash table而不是tree的方法。
unordered_set<int>, unordered_set<bool>, etc

7.3.3. Maps

table()match()关系密切。

Ordered map: std::map

Unordered map: std::unordered_map

Since maps have a value and a key, you need to specify both types when initialising a map:

 map<double, int> unordered_map<int, double>.

8. 与R环境的互动

通过EnvironmentRcpp可以获取当前R全局环境(Global Environment)中的变量和载入的函数,并可以对全局环境中的变量进行修改。我们也可以通过Environment获取其他R包中的函数,并在Rcpp中使用。

获取其他R包中的函数

Rcpp::Environment stats("package:stats");
Rcpp::Function rnorm = stats["rnorm"];
return rnorm(10, Rcpp::Named("sd", 100.0));

获取R全局环境中的变量并进行更改
假设R全局环境中有一个向量x=c(1,2,3),我们希望在Rcpp中改变它的值。

Rcpp::Environment global = Rcpp::Environment::global_env();//获取全局环境并赋值给Environment型变量global
Rcpp::NumericVector tmp = global["x"];//获取x
tmp=pow(tmp,2);//平方
global["x"]=tmp;//将新的值赋予到全局环境中的x

获取R全局环境中的载入的函数
假设全局环境中有R函数funR,其定义为:

x=c(1,2,3);
funR<-function(x){
  return (-x);
}

并有R变量x=c(1,2,3)。我们希望在Rcpp中调用此函数并应用在向量x上。

#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector funC() {
  Rcpp::Environment global =
    Rcpp::Environment::global_env();
  Rcpp::Function funRinC = global["funR"];
  Rcpp::NumericVector tmp = global["x"];
  return funRinC(tmp);
}

9. 用Rcpp创建R包

见此文

利用Rcpp和RcppArmadillo创建R包

10. 输入和输出示例

如何传递数组

如果要传递高维数组,可以将其存为向量,并附上维数信息。有两种方式:

通过.attr("dim")设置维数

NumericVector可以包含维数信息。数组可以用过NumericVector输出到R中。此NumericVector可以通过.attr(“dim”)设置其维数信息。

// Dimension最多设置三个维数
output.attr("dim") = Dimension(3,4,2);
// 可以给.attr(“dim”)赋予一个向量,则可以设置超过三个维数
NumericVector dim = NumericVector::create(2,2,2,2);
output.attr("dim") = dim;

示例:

// 返回一个3*3*2数组
RObject func(){
  arma::vec long_vec(18,arma::fill::randn);
  vector<double> long_vec2 = conv_to<vector<double>>::from(long_vec);
  NumericVector output = wrap(long_vec2);
  output.attr("dim")=Dimension(3,3,2);
  return wrap(output);
}
// 返回一个2*2*2*2数组 
// 注意con_to<>::from()
RObject func(){
  arma::vec long_vec(16,arma::fill::randn);
  vector<double> long_vec2 = conv_to<vector<double>>::from(long_vec);
  NumericVector output = wrap(long_vec2);
  NumericVector dim = NumericVector::create(2,2,2,2);
  output.attr("dim")=dim;
  return wrap(output);
}

另外建立一个向量存维数,在R中再通过.attr("dim")设置维数

函数返回一维STL vector

自动转化为R中的向量

vector<double> func(NumericVector x){
  vector<double> vec;
  vec = as<vector<double>>(x);
  return vec;
}
NumericVector func(NumericVector x){
  vector<double> vec;
  vec = as<vector<double>>(x);
  return wrap(vec);
}
RObject func(NumericVector x){
  vector<double> vec;
  vec = as<vector<double>>(x);
  return wrap(vec);
}

函数返回二维STL vector

自动转化为R中的list,list中的每个元素是一个vector。

vector<vector<double>> func(NumericVector x) {
  vector<vector<double>> mat;
  for (int i=0;i!=3;++i){
    mat.push_back(as<vector<double>>(x));
  }
  return mat;
}
RObject func(NumericVector x) {
  vector<vector<double>> mat;
  for (int i=0;i!=3;++i){
    mat.push_back(as<vector<double> >(x));
  }
  return wrap(mat);
}

返回Armadillo matrix, Cube 或 field

自动转化为R中的matrix

NumericMatrix func(){
  arma::mat A(3,4,arma::fill::randu);
  return wrap(A);
}
arma::mat func(){
  arma::mat A(3,4,arma::fill::randu);
  return A;
}

自动转化为R中的三维array

arma::cube func(){
  arma::cube A(3,4,5,arma::fill::randu);
  return A;
}
RObject func(){
  arma::cube A(3,4,5,arma::fill::randu);
  return wrap(A);
}

自动转化为R list,每个元素存储一个R向量,但此向量有维数信息(通过.Internal(inspect())查询)。

RObject func() {
  arma::cube A(3,4,2,arma::fill::randu);
  arma::cube B(3,4,2,arma::fill::randu);
  arma::field <arma::cube> F(2,1);
  F(0)=A;
  F(1)=B;
  return wrap(F);
}

关于“R语言中Rcpp基础知识点有哪些”这篇文章就分享到这里了,希望

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/73736.html

(0)

相关推荐

  • 如何进行C#实现AOP微型框架基础的分析

    技术如何进行C#实现AOP微型框架基础的分析如何进行C#实现AOP微型框架基础的分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在向大家详细介绍C#实现A

    攻略 2021年11月24日
  • 香港VPS or 香港服务器 如何选择

    技术香港VPS or 香港服务器 如何选择选择香港地区的IDC产品搭建网站有不少选择,比较常用的是香港服务器和香港VPS,那么二者之间有什么区别,应该如何选择呢,下面就来简单介绍一下香港VPS 香港VPS租用是一个常见的

    礼包 2021年12月15日
  • Docker原理、架构与应用是什么

    技术Docker原理、架构与应用是什么本篇内容主要讲解“Docker原理、架构与应用是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Docker原理、架构与应用是什么”吧

    攻略 2021年12月13日
  • 【2021-11-29】连岳摘抄

    技术【2021-11-29】连岳摘抄 【2021-11-29】连岳摘抄23:59如果你热爱工作,你每天就会尽自己所能力求完美,而不久,你周围的每一个人也会从你这里感染到这种热情。——山姆·沃尔顿人不想学

    礼包 2021年12月1日
  • 字母顺序,bpmf拼音26个字母顺序

    技术字母顺序,bpmf拼音26个字母顺序声母 b p m f d t n l g k h j q x zh ch sh r z c s y w 韵母 a o

    生活 2021年10月23日
  • mshflexgrid数据表格怎样绑定数据库

    技术mshflexgrid数据表格怎样绑定数据库这篇文章将为大家详细讲解有关mshflexgrid数据表格怎样绑定数据库,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。ms

    攻略 2021年12月1日