以前介紹瞭如何製做併發布本身的R語言包。這篇文章介紹怎麼製做一個C++的R包,也就是使用Rcpp製做R包。html
其實製做Rcpp的R包和普通的R包製做仍是有區別的。本人也嘗試按照以前的作法,在R腳本里面使用cppFunction()寫一個C++腳本,以腳本運行的時候很完美,沒有出現任何錯誤,可是當構建成包時,安裝以後每次運行都出現錯誤。因此不得不嘗試其餘方法建立Rcpp的R包。git
Rcpp其實是R語言調用C++的一個接口,而C++在運行速度上要比R語言快成百上千倍!!好比有以下兩個數據:github
> aa pos 1 2 2 4 3 6 > bb start end 1 1 3 2 5 8 3 7 10
其中aa$pos表示一段DNA序列的SNP位點,bb表示該DNA序列上的基因位置(包括基因起始位置和終止位置),若是你要判斷aa中全部的SNP是否在基因上,咱們一般的作法是寫兩個for循環,用aa中的每個SNP位點去判斷bb中的每個基因。也就是要有3 * 3 = 9次運算。可是當數據量足夠大的時候,假若有幾十萬SNP位點,有幾萬基因序列,那麼這個循環可能要執行成百上千萬次!這對R語言來講,運行時間會以小時來計了。
而C++能夠在一兩分鐘內完成!
參考:如何提高備受詬病的R的運行速度markdown
和以前的介紹同樣,仍是要安裝並加載devtools 和 roxygen2兩個工具包。
而後建立一個路徑(「~/Documents/CheckOverlap),在此路徑內構建R包併發
library(devtools) library(roxygen2) setwd("~/Documents/") create("CheckOverlap") setwd("./CheckOverlap/") devtools::use_rcpp() #會自動生成一些相關文件
和以前的文件結構不一樣,這時會出現一個src文件夾。
(2)寫C++函數
按照你的目的參考以下格式寫C++函數,並將該文件保存成「~/Documents/CheckOverlap/src/CheckPointRange.cpp「。
若是是在Rstudio中,能夠「新建」 —「C++文件「,這樣會自動生成一個模版。ssh
// CheckPointRange.cpp #include <Rcpp.h> using namespace Rcpp; //'@title Check if points in segments //'@description //'To check if a number in a range. //'Return a vector of 0,1 if the the number //'in a range(1) or not (0). //'@param pos a vector of numbers of points //'@param start a vector of numbers of starting position //'@param end a vector of numbers of ending position //'@examples //'aa <- c(2,4,6) //'bb1 <- c(1,5,7) //'bb2 <- c(3,8,10) //'CheckPoint(aa,bb1,bb2) //'@useDynLib CheckOverlap //'@import Rcpp //'@export // [[Rcpp::export]] IntegerVector CheckPoint(IntegerVector pos, IntegerVector start, IntegerVector end){ int pos_size=pos.size(); int seg_size=start.size(); IntegerVector ismask(pos_size); for (int i=0; i<pos_size; i++) { for (int j=0; j<seg_size; j++){ if ( pos[i]>=start[j] && pos[i]<=end[j] ){ ismask[i]=1; break; } } } return ismask; } #include <Rcpp.h> using namespace Rcpp; //'@title Check if segments contain point //'@description //'To check if a range contains points. //'Return a vector of 0,1 //'with 1 = contain points, 0 = not contain points. //'@param pos a vector of numbers of points //'@param start a vector of numbers of starting position //'@param end a vector of numbers of ending position //'@examples //'aa <- c(2,4,6) //'bb1 <- c(1,5,7) //'bb2 <- c(3,8,10) //'CheckRange(aa,bb1,bb2) //'@useDynLib CheckOverlap //'@import Rcpp //'@export // [[Rcpp::export]] IntegerVector CheckRange(IntegerVector pos, IntegerVector start, IntegerVector end){ int pos_size=pos.size(); int seg_size=start.size(); IntegerVector ismask1(pos_size); for (int i=0; i<seg_size; i++) { for (int j=0; j<pos_size; j++){ if ( pos[j]>=start[i] && pos[j]<=end[i] ){ ismask1[i]=1; break; } } } return ismask1; }
注意,這兒寫了兩個函數,一個是用來判斷SNP是夠在基因上(CheckPoint),另外一個用來判斷基因上是否含有SNP位點(CheckRange)。
其中不少關鍵字是不可缺乏的,好比include, using, useDynLib 你的包名, import, export, [[Rcpp::export]]等。
而後ide
Rcpp::sourceCpp("./src/CheckPointRange.cpp")
或者在Rstudio點擊「Source「函數
setwd("~/Documents/CheckOverlap/") document()
這個時候去檢查CheckOverlap文件夾,會有不少自動生成的文件,包括NAMESPACE、DESCRIPTION,在src子文件夾中,有.so, .o等文件名後綴的的文件。
在R子文件夾中,出現了一個RcppExports.R的文件,這個文件就至關於該包的主文件。
下面檢查包,看看是否存在錯誤。工具
setwd("..") devtools::check("CheckOverlap")
setwd("~/Documents/") install("CheckOverlap") aa <- c(2,4,6) bb1 <- c(1,5,7) bb2 <- c(3,8,10) CheckOverlap::CheckPoint(aa,bb1,bb2) CheckOverlap::CheckRange(aa,bb1,bb2)
輸出結果爲spa
[1] 1 0 1 # 即SNP2和6位於基因上 [1] 1 1 0 # 即基因片斷1-3和5-8含有SNP位點。
至此,R包的構建已經完成
三、R包``發佈
設置GitHub帳戶,參考:
https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/
https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/
在本身的GitHub帳戶上建立一個目錄,用來存放你要發佈的R包。
在本地terminal中:
cd ~/Documents/CheckOverlap/ git init git add * git commit -m "first version" git remote add wyg git@github.com:Yiguan/CheckOverlap.git git push -u wyg master
建立,發佈;所有完成!
一個須要幾個小時完成的任務,如今只須要一兩分鐘就能夠完成!
======= THE END =======
參考資料:
https://www.r-bloggers.com/rcpp-and-roxygen2/
http://r-pkgs.had.co.nz/src.html
http://www.deanbodenham.com/learn/make-an-r-package-using-rcpp.html