R Language Cross-premises call C + +
R's Geek Ideal series of articles, covering the ideas of R, use, tools, innovation and a series of key points, in my personal learning and experience to interpret the powerful R.
The R language, as a statistical language, has been shining brightly in niche areas. Until the outbreak of big data, the R language became a hot tool for data analysis. As more and more engineering background people join, the R language community is growing rapidly. Now it's not just statistics, education, banking, e-commerce, Internet ... all in the R language.
To become an ideal geek, we can not stay in the grammar, to grasp the solid mathematics, probability, statistical knowledge, but also to have the spirit of innovation, the R language to play in all fields. Let's move together and start the Geek ideal for R.
About
- Zhang Dan (Conan), programmer R,nodejs,java
- Weibo: @Conan_Z
- Blog:http://blog.fens.me
- Email: [Email protected]
Reprint please specify the source:
Http://blog.fens.me/r-cpp-rcpp
Objective
Using the R language has been a long time, for many R packages have been understood, but not touch the C + + related parts, which may be a big reason for my long-term use of Java background. But with the development of multi-language, the popularity of cross-language application, the way to get through the boundaries of each language is also mature. Having r and C + + communicate, has become very simple.
Keep up with the cross-language pace, open R and C + + channels, let C + + to solve R performance criticism.
Directory
- A brief introduction to Rcpp
- 5 minutes to get started
- Data type conversions
1. Brief introduction of Rcpp
The Rcpp package is a communication component package that breaks through the R and C + + languages, providing mutual invocation of R and C + + functions. The R and C + + language data types are fully mapped through the Rcpp package.
Rcpp's official website: https://cran.r-project.org/web/packages/Rcpp/index.html
This article as an introductory tutorial, just a brief introduction, how to get through the R language and C + + communication channels, do not do in-depth discussion. R language and other languages also have similar communication implementations, R language and Java calls, please refer to the article Rjava R and Java high-speed Channel, R language and Nodejs calls, please refer to the article Nodejs and R cross-platform communication.
2.5 minutes to get started
As a 5-minute tutorial, we only talk about examples without APIs.
The system environment of this article
- Win10 64bit
- R version 3.2.3 (2015-12-10)
Due to the need for rtools support in the context of Windows systems, it is necessary to manually download the corresponding version of the RTOOSL package. My R language version is 3.2.3, so I need to install Rtools33.exe. Install EXE program will not say more, double-click to complete.
Download the Rcpp package, install it, and one line of code is done.
> install.packages("Rcpp")trying URL ‘https://mirrors.tuna.tsinghua.edu.cn/CRAN/bin/windows/contrib/3.2/Rcpp_0.12.6.zip‘Content type ‘application/zip‘ length 3221864 bytes (3.1 MB)downloaded 3.1 MBpackage ‘Rcpp’ successfully unpacked and MD5 sums checkedWarning in install.packages : cannot remove prior installation of package ‘Rcpp’The downloaded binary packages are inC:\Users\tinkpad\AppData\Local\Temp\RtmpKkg8zo\downloaded_packages
2.1 Starting from Hello World
Start with a simple program Hello World and let the R language program invoke the Hello () function in C + +. I need to create a new 2 files and put them in the same directory.
- Source files for demo.cpp,c++ programs
- Demo.r,r Program Source files
First, edit demo.cpp and define the Hello () function.
~ notepad demo.cpp#include <Rcpp.h>#include <string> using namespace std;using namespace Rcpp;//[[Rcpp::export]]string hello(string name) { cout << "hello " << name << endl; return name;}/*** Rhello(‘world‘)hello(‘Conan‘)*/
The above Rcpp code, we can see from 3 parts.
- #include和using部分: The declaration for the package reference and namespace. <Rcpp.h> and namespace rcpp are necessary to load, and because of the use of string types as parameters and return values, <string> and namespace std are required.
- Functional Functions Section: We define a hello (string name) function, one argument is a string type, and the return value is a string type. It is important to emphasize that the function opening to R must add//[[rcpp::export]] to the comment declaration .
- Code execution: The code for the R language, with/*** R and * * included, is executed by default.
Edit DEMO.R to invoke the Hello () function of demo.cpp.
~ notepad demo.rlibrary(Rcpp)sourceCpp(file=‘demo.cpp‘)hello(‘R‘)
Code that executes the R language
# 加载Rcpp包> library(Rcpp)# 编译和加载demo.cpp文件> sourceCpp(file=‘demo.cpp‘)# 执行封装在demo.cpp中的R代码> hello(‘world‘)hello world[1] "world"> hello(‘Conan‘)hello Conan[1] "Conan"# 执行hello函数> hello(‘R‘)hello [1]R "R"
A very simple HelloWorld program, this is done.
2.2 R and Rcpp mixed-write code
The above 2 lines of code, completed R on C + + program calls, Sourcecpp () function is really powerful. In fact, the sourcecpp () function also provides a way to write code that embeds C + + code directly in R's code.
sourceCpp(code=‘ #include >Rcpp.h< #include >string< using namespace std; using namespace Rcpp; //[[Rcpp::export]] string hello(string name) { cout << "hello " << name << endl; return name; }‘)hello(‘R2‘)
Run code
> sourceCpp(code=‘+ #include >Rcpp.h<+ #include >string<+ + using namespace std;+ using namespace Rcpp;+ + //[[Rcpp::export]]+ string hello(string name) {+ cout << "hello " << name << endl; + return name;+ }+ ‘)> hello(‘R2‘)hello R2[1] "R2"
This multi-lingual, mixed-write syntax is not recommended, but it's handy for just a few lines of code.
2.2 Using Rstudioide to generate CPP files
If you use the Rstudio IDE, it will be very handy to develop a new C + + program and generate a standard code template.
The resulting code template is as follows
#include <Rcpp.h>using namespace Rcpp;// This is a simple example of exporting a C++ function to R. You can// source this function into an R session using the Rcpp::sourceCpp // function (or via the Source button on the editor toolbar). Learn// more about Rcpp at://// http://www.rcpp.org/// http://adv-r.had.co.nz/Rcpp.html// http://gallery.rcpp.org///// [[Rcpp::export]]NumericVector timesTwo(NumericVector x) { return x * 2;}// You can include R code blocks in C++ files processed with sourceCpp// (useful for testing and development). The R code will be automatically // run after the compilation.///*** RtimesTwo(42)*/
With Rstudio you can quickly generate a standard code template that can be used immediately.
3. Data type Conversion
In the example above, we tested the invocation of the string type. The R language has a variety of data types, and I'll test it next!
3.1 Basic Types
Base type, C + + corresponds to the default mapping of R languages. The code portion of C + + is as follows:
// [[Rcpp::export]]char char_type(char x){ return x;}// [[Rcpp::export]]int int_type(int x){ return x;}// [[Rcpp::export]]double double_type(double x){ return x;}// [[Rcpp::export]]bool bool_type(bool x){ return x;}// [[Rcpp::export]]void void_return_type(){ Rprintf( "return void" );}
Execute R language Call
# char类型> a1<-char_type(‘a‘)> a1;class(a1) # 默认对应R的character类型[1] "a"[1] "character"> char_type(‘bbii‘) # 只处理字符串的第一个字节[1] "b"# int类型 > a2<-int_type(111)> a2;class(a2) # 默认对应R的integer类型[1] 111[1] "integer" > int_type(111.1) # 直接去掉小数位[1] 111# double类型 > a3<-double_type(111.1)> a3;class(a3) # 默认对应R的numeric类型[1] 111.1[1] "numeric"> double_type(111)[1] 111# boolean类型 > a4<-bool_type(TRUE)> a4;class(a4) # 默认对应R的logical类型[1] TRUE[1] "logical"> bool_type(0) # 0为FALSE[1] FALSE> bool_type(1) # 非0为TRUE[1] TRUE# 无参数无返回值 的函数> a5<-void_return_type()return void> a5;class(a5) # 返回值为NULLNULL[1] "NULL"
3.2 Vector Type
Vector type, C + + corresponds to the default mapping of the R language. The code portion of C + + is as follows:
// [[Rcpp::export]]CharacterVector CharacterVector_type(CharacterVector x){ return x;}// [[Rcpp::export]]StringVector StringVector_type(StringVector x){ return x;}// [[Rcpp::export]]NumericVector NumericVector_type(NumericVector x) { return x;}// [[Rcpp::export]]IntegerVector IntegerVector_type(IntegerVector x) { return x;}// [[Rcpp::export]]DoubleVector DoubleVector_type(DoubleVector x){ return x;}// [[Rcpp::export]]LogicalVector LogicalVector_type(LogicalVector x){ return x;}// [[Rcpp::export]]DateVector DateVector_type(DateVector x){ return x;}// [[Rcpp::export]]DatetimeVector DatetimeVector_type(DatetimeVector x){ return x;}
Execute R language Call
# character vector > A6<-charactervector_type (C (' abc ', ' 12345 ') > A6;class (A6) # The default corresponds to the character type of R [1] "abc" "12345" [1] "character" > Charactervector_type (C (' abc ', 123.5, NA, TRUE)) # NA does not process [1] "ABC" "123.5" NA "TRUE" # string vector, exactly the same as character vector > A7<-stringvector_type (C (' abc ', ' 12345 ')) > A7;class (A7) # default corresponds to R's character type [1] "abc" "12345" [1] "character" > Stringvector_type (C (' abc ', 123.5, NA , true)) [1] "abc" "123.5" NA "TRUE" # numeric vector > A8<-numericvector_type (rnorm (5)) > A8;class (A8) # default corresponds to R's numeric type [1] -0.2813472-0.2235722-0.6958443-1.5322172 0.5004307[1] "numeric" > Nume Ricvector_type (C (Rnorm (5), na,true)) # NA not processed, TRUE for 1[1] 0.1700925 0.5169612-0.3622637 1.0763204-0.5729958[6] NA 1.0000000# integer vector > A9<-integervector_type (C (11,9.9,1.2)) # directly remove decimal digits > A9;class (A9) # default corresponds to R's integer type [1] 9 1[1] "integer" > Integervector_type (C (11,9.9,1.2,na,true)) # NA not processed, TRUE to 1[1] 11 9 1 NA # double vector, same numeric vector > A10<-doublevector_type (rnorm (5)) > A10;class (A10) # The default corresponds to R's numeric type [1] 0.9400947-0.8976913 0.2744319-1.5278219 1.2010569[1] "numeric" > Doublevector_type (C (Rnorm (5), na,true) # na not processed, TRUE 1[1] 2.0657148 0.2810003 2.1080900-1.2783693 0.2198551[6] NA 1.0000000# logi Cal Vector > A11<-logicalvector_type (C (true,false)) > A11;class (A11) # Default logical type corresponding to R [1] True false[1] "logical" > Logicalvector_type (C (True,false,true,0,-1,na)) # NA not processed, 0 is FALSE, not 0 is true[1] TRUE FALSE True FALSE true NA # Date vector > A12<-datevector_type (C (Sys.date (), as. Date (' 2016-10-10 ')) > A12;class (A12) # Default corresponds to the date type of R [1] "2016-08-01" "2016-10-10" [1] "D Ate "> Datevector_type (C (Sys.date (), as. Date (' 2016-10-10 '), NA,TRUE,FALSE) # NA does not process, True is 1970-01-02, False is 1970-01-01[1] "2016-08-01" "2016-10-10" NA "1970-01-02" [5] "1970-01-01" # DateTime vectors > A13<-datetimevector_type (C (Sys.time (), as. POSIXCT (' 2016-10-10 '))) > A13;class (A13) # default corresponds to R's POSIXct type [1] "2016-08-01 20:05:25 CST" "2016-10-10 00:00:00 CST" [1] "POSIXct" "Posixt" > Datetimevector_type (C (Sys.time (), as. POSIXCT (' 2016-10-10 '), Na,true,false)) # NA does not process [1] "2016-08-01 20:05:25 CST" "2016-10-10 00:00:00 CST" [3] Na "1970-01-01 08:00:01 CST" [5] "1970-01-01 08:00:00 CST"
3.3 Matrix Types
Matrix type, C + + corresponds to the default mapping of the R language. The code portion of C + + is as follows:
// [[Rcpp::export]]CharacterMatrix CharacterMatrix_type(CharacterMatrix x){ return x;}// [[Rcpp::export]]StringMatrix StringMatrix_type(StringMatrix x){ return x;}// [[Rcpp::export]]NumericMatrix NumericMatrix_type(NumericMatrix x){ return x;}// [[Rcpp::export]]IntegerMatrix IntegerMatrix_type(IntegerMatrix x){ return x;}// [[Rcpp::export]]LogicalMatrix LogicalMatrix_type(LogicalMatrix x){ return x;}// [[Rcpp::export]]ListMatrix ListMatrix_type(ListMatrix x){ return x;}
Execute R language Call
# character Matrix > A14<-charactermatrix_type (Matrix (letters[1:20],ncol=4)) > A14;class (A14) [, 1] [, 2] [, 3] [, 4][1 ,] "A" "F" "K" "P" [2,] "B" "G" "L" "Q" [3,] "C" "H" "M" "R" [4,] "D" "I" "N" "S" [5,] "E" "J" "O" "T" [1] "Matrix" # string matrix, same as character matrix > A15<-stringmatrix_type (Matrix (letters[1:20],ncol=4)) > A1 5;class (A15) [, 1] [, 2] [, 3] [, 4][1,] "A" "F" "K" "P" [2,] "B" "G" "L" "Q" [3,] "C" "H" "M" "R" [4,] "D" "I" "N" "S" [5,] "E" "J" "O" "T" [1] "Matrix" # Numeric Matrix > A16<-numericmatrix_type (Matrix (rnorm), ncol=4) > A16 ; Class (A16) [, 1] [, 2] [, 3] [, 4][1,] 1.2315498 2.3234269 0.5974143 0.9072356[2,] 0.3484811 0.3814024-0.2018324 0.8717205[3,]-0.2025285 2.1076947-0.3433948 1.1523710[4,] -1.4948252-0.7724951-0.7681800-0. 5406494[5,] 0.4815904 1.4930873-1.1444258 0.2537099[1] "Matrix" # integer matrix > A17<-integermatrix_type (Matrix (seq (1,10,length.out =), NCOl=4) > A17;class (A17) [, 1] [, 2] [, 3] [, 4][1,] 1 3 5 8[2,] 1 3 6 8[3,] 1 4 6 9[4 ,] 2 4 7 9[5,] 2 5 7 10[1] "Matrix" # Logical Matrix > A18<-logicalmatrix_type (Matrix (C (Rep (true,5) , Rep (false,5), Rnorm (Ten)), ncol=4)) > A18;class (A18) [, 1] [, 2] [, 3] [, 4][1,] true false true true[2,] true false true True[3,] True false true True[4,] true false true True[5,] true false true true[1] "Matrix" # list matrix, supports multiple types of matrices > a19<- Listmatrix_type (Matrix (Rep (list (a=1,b= ' 2 ', c=na,d=true), ten), ncol=5) > A19;class (A19) [, 1] [, 2] [, 3] [, 4] [, 5][1,] 1 1 1 1 1 [2,] "2" "2" "2" "2" "2" [3,] na na Na na na [4,] True True True true[5,] 1 1 1 1 1 [6,] "2" "2" "2" "2" "2" [7,] na na na na na [8,] True true true true[1] "Matrix"
3.4 Other data types
Other data types include object types such as the R language-specific data type data frame (data.frame), Environment Space (environment), S3,S4,RC, and so on.
// [[Rcpp::export]]Date Date_type(Date x){ return x;}// [[Rcpp::export]]Datetime Datetime_type(Datetime x){ return x;}// [[Rcpp::export]]S4 S4_type(S4 x){ return x;}// [[Rcpp::export]]RObject RObject_type(RObject x){ return x;}// [[Rcpp::export]]SEXP SEXP_type(SEXP x){ return x;}// [[Rcpp::export]]Environment Environment_type(Environment x){ return x;}
Execute R language Call
# Data.frame type > A19<-dataframe_type (Data.frame (A=rnorm (3), b=1:3)) > A19;class (A19) a b1-1.8844994 12 0 .6053935 23-0.7693985 3[1] "data.frame" # List type > A20<-list_type (List (a=1,b= ' 2 ', c=na,d=true)) > A20;class (A20 ) $a [1] 1$b[1] "2" $c [1] na$d[1] true[1] "list" # Date type > A21<-date_type (sys.date ()) > A21;class (A21) [1] " 2016-08-01 "[1]" Date "> Date_type (Sys.time ()) # cannot properly handle data of type POSIXCT [1]" 4026842-05-26 "# Posixct type > A22 <-datetime_type (Sys.time ()) > A22;class (A22) [1] "2016-08-01 20:27:37 CST" [1] "POSIXct" "Posixt" > Datetime_ Type (Sys.date ()) # does not correctly handle data of Date type [1] "1970-01-01 12:43:34 CST" # S3 object type, corresponding to S4 type definition > setclass ("Person", slots =list (name= "character", age= "numeric") > S4<-new ("Person", name= "F", age=44) > A23<-s4_type (S4) > A23; Class (A23) An object of class ' person ' Slot ' name ': [1] ' F ' slot ' age ': [1] 44[1] ' person ' attr (, "package") [1] ". Globalenv "# S3 Object-oriented type, no corresponding type, passed robject to Value > S3<-structure (2, Class = "foo") > A24<-robject_type (S3) > A24;class (A24) [1] 2attr (, "class") [1] "foo" [1] "foo" # robject can also handle S4 objects > A25<-robject_type (S4) > A25;class (A25) An object of class ' person ' Slot ' name ': [1] ' F ' slot ' age ': [1] 44[1] ' person ' attr (, "package") [1] ". Globalenv "# robject can also handle RC objects > User<-setrefclass (" User ", Fields=list (name=" character ")) > Rc<-user$new ( Name= "U1") > A26<-robject_type (RC) > A26;class (A26) Reference class object of Class "User" Field "name": [1] "U1" [1 ] "User" attr (, "package") [1] ". Globalenv "# robject can also handle function types > A27<-robject_type (function (x) x+2) > A27;class (A27) function (x) x+2[1]" Function "# Environment type > A28<-environment_type (new.env ()) > A28;class (a28) <environment: 0X0000000015350A80>[1] "Environment" # Sexp for any type, and then type judgment by specific invocation > Sexp_type (' Fdafdaa ') [1] "Fdafdaa" > Sexp_ Type (RC) Reference class object of Class "User" Field "name": [1] "U1" > Sexp_type (Data.frame (A=rnorm (3), b=1:3)) A b1-0.5396140 12 0.169479923-1.8818596 3> Sexp_type (function (x) x+2) function (x) x+2
Finally, summarize the relationship between the types in R and Rcpp.
C + + types |
Type R |
Char |
Character |
Int |
Integer |
Double |
Numeric |
bool |
Logical |
Rcpp::D ate |
Date |
Rcpp::D atetime |
POSIXct |
Rcpp::charactervector |
Character |
Rcpp::stringvector |
Character |
Rcpp::numericvector |
Numeric |
Rcpp::integervector |
Integer |
Rcpp::D oublevector |
Numeric |
Rcpp::logicalvector |
Logical |
Rcpp::D atevector |
Date |
Rcpp::D atetimevector |
POSIXct |
Rcpp::charactermatrix |
Matrix |
Rcpp::stringmatrix |
Matrix |
Rcpp::numericmatrix |
Matrix |
Rcpp::integermatrix |
Matrix |
Rcpp::logicalmatrix |
Matrix |
Rcpp::listmatrix |
Matrix |
Rcpp::D ataframe |
Data.frame |
Rcpp::list |
List |
Rcpp::s4 |
S4 |
Rcpp::environment |
Environment |
Rcpp::robject |
Any type |
Rcpp::sexp |
Any type |
This article simply introduces a method of calling C + + program through R language Rcpp package, the key point of the call is the matching of data type, and from guaranteeing the data transmission between r language and C + +. From the above tests, all data types in the R language can be mapped to C + + programs through the Rcpp package. Next, we will be able to according to their own needs, some of the more attention to the performance of the program in C + + to achieve, thus improving the computational efficiency.
Reprint please specify the source:
Http://blog.fens.me/r-cpp-rcpp
R language calls C + +