R語言基因組數據分析可能會用到的data.table函數整理

分類:IT技術 時間:2017-03-25

    R語言data.table包是自帶包data.frame的升級版,用於數據框格式數據的處理,最大的特點快。包括兩個方面,一方面是寫的快,代碼簡潔,只要一行命令就可以完成諸多任務,另一方面是處理快,內部處理的步驟進行了程序上的優化,使用多線程,甚至很多函數是使用C寫的,大大加快數據運行速度。因此,在對大數據處理上,使用data.table無疑具有極高的效率。這裏主要介紹在基因組數據分析中可能會用到的函數。

 

fread

    做基因組數據分析時,常常需要讀入處理大文件,這個時候我們就可以舍棄read.table,read.csv等,使用讀入速度快的fread函數

    fread(input, sep="auto", sep2="auto", nrows=-1L, header="auto", na.strings="NA", file,
        stringsAsFactors=FALSE, verbose=getOption("datatable.verbose"), autostart=1L,
        skip=0L, select=NULL, drop=NULL, colClasses=NULL,
        integer64=getOption("datatable.integer64"),# default: "integer64"
        dec=if (sep!=".") "." else ",", col.names,
        check.names=FALSE, encoding="unknown", quote="\"",
        strip.white=TRUE, fill=FALSE, blank.lines.skip=FALSE, key=NULL,
        showProgress=getOption("datatable.showProgress"), # default: TRUE
        data.table=getOption("datatable.fread.datatable") # default: TRUE
      )

 

     input    輸入的文件,或者字符串(至少有一個"\n");
     sep    列之間的分隔符;
     sep2    分隔符內再分隔的分隔符,功能還沒有應用;
     nrow    讀取的行數,默認-l全部,nrow=0僅僅返回列名;
     header    第一行是否是列名;
     na.strings    對NA的解釋;
     file    文件路徑,再確保沒有執行shell命令時很有用,也可以在input參數輸入;
     stringsASFactors    是否轉化字符串為因子;
     verbose    是否交互和報告運行時間;
     autostart    機器可讀這個區域任何行號,默認1L,如果這行是空,就讀下一行;
     skip    跳過讀取的行數,為1則從第二行開始讀,設置了這個選項,就會自動忽略autostart選項,也可以是一個字符,skip="string",那麽會從包含該字符的行開始讀;
     select    需要保留的列名或者列號,不要其它的;
     drop    需要取掉的列名或者列號,要其它的;
     colClasses    類字符矢量,用於罕見的覆蓋而不是常規使用,只會使一列變為更高的類型,不能降低類型;
     integer64    讀如64位的整型數;
     dec    小數分隔符,默認"."不然就是","
     col.names    給列名,默認試用header或者探測到的,不然就是V+列號;
     encoding    默認"unknown",其它可能"UTF-8"或者"Latin-1",不是用來重新編碼的,而是允許處理的字符串在本機編碼;
     quote    默認""",如果以雙引開頭,fread強有力的處理裏面的引號,如果失敗了就會用其它嘗試,如果設置quote="",默認引號不可用
     strip.white    默認TRUE,刪除結尾空白符,如果FALSE,只取掉header的結尾空白符;
     fill    默認FALSE,如果TRUE,不等長的區域可以自動填上,利於文件順利讀入;
     blank.lines.skip    默認FALSE,如果TRUE,跳過空白行
     key    設置key,用一個或多個列名,會傳遞給setkey
     showProgress    TRUE會顯示腳本進程,R層次的C代碼
     data.table    TRUE返回data.table,FALSE返回data.frame


可見1.8GB的數據讀入94秒,讀入文件速度非常快

 

fwrite

 

    對數據框數據進行處理後,需要保存到文件,我們就可以使用fwrite多線程寫出,速度特別快

 

    fwrite(x, file = "", append = FALSE, quote = "auto",
    sep = ",", sep2 = c("","|",""),
    eol = if (.Platform$OS.type=="Windows") "\r\n" else "\n",
    na = "", dec = ".", row.names = FALSE, col.names = TRUE,
    qmethod = c("double","escape"),
    logicalAsInt = FALSE, dateTimeAs = c("ISO","squash","epoch","write.csv"),
    buffMB = 8L, nThread = getDTthreads(),
   showProgress = getOption("datatable.showProgress"),
   verbose = getOption("datatable.verbose"))

 

     x    具有相同長度的列表,比如data.frame和data.table等;
     file    輸出文件名,""意味著直接輸出到操作臺;
     append    如果TRUE,在原文件的後面添加;
     quote    如果"auto",因子和列名只有在他們需要的時候才會被加上雙引號,例如該部分包括分隔符,或者以"\n"結尾的一行,或者雙引號它自己,如果FALSE,那麽區域不會加上雙引號,如果TRUE,就像寫入CSV文件一樣,除了數字,其它都加上雙引號;
     sep    列之間的分隔符;
     sep2    對於是list的一列,寫出去時list成員間以sep2分隔,它們是處於一列之內,然後內部再用字符分開;
     eol    行分隔符,默認Windows是"\r\n",其它的是"\n";
     na,na    值的表示,默認"";
     dec    小數點的表示,默認".";
     row.names    是否寫出行名,因為data.table沒有行名,所以默認FALSE;
     col.names     是否寫出列名,默認TRUE,如果沒有定義,並且append=TRUE和文件存在,那麽就會默認使用FALSE;
     qmethod    怎樣處理雙引號,"escape",類似於C風格,用反斜杠逃避雙引,“double",默認,雙引號成對;
     logicalAsInt    邏輯值作為數字寫出還是作為FALSE和TRUE寫出;
     dateTimeAS    決定 Date/IDate,ITime和POSIXct的寫出,"ISO"默認,-2016-09-12, 18:12:16和2016-09-12T18:12:16.999999Z;"squash",-20160912,181216和20160912181216999;"epoch",-17056,65536和1473703936;"write.csv",就像write.csv一樣寫入時間,僅僅對POSIXct有影響,as.character將digits.secs轉化字符並通過R內部UTC轉回本地時間。前面三個選項都是用新的特定C代碼寫的,較快;
     buffMB    每個核心給的緩沖大小,在1到1024之間,默認80MB;
     nThread    用的核心數;
     showProgress    在工作臺顯示進程,當用file==""時,自動忽略此參數;
     verbose    是否交互和報告時間

 

 dcast.data.table

   和reshape2包的dcast一樣, 這個函數用來重鑄表格,並且再在大數據的處理上,比reshape2的內存更優化,函數效果如下  

                                          

           原表格                                                       鑄造後(v4作為value)  

 

    dcast(data, formula, fun.aggregate = NULL, sep = "_",
        ...,  subset = NULL, margins=NULL,fill = NULL,
        drop = TRUE, value.var = guess(data),
        verbose = getOption("datatable.verbose"))

   data   一個data.table;

    formula    要鑄造的表格的LHS~RHS格式;LHS和RHS可以是"..."和“.",其中"..."代表全部變量,"."代表無變量;

    fun.aggregate    是否在鑄造之前匯總,應提供函數list(比如mean,sum或者c(sum,mean)),默認length;

    sep    鑄造的時候連接字符變量的連接符,默認_;

    subset   指定要鑄造的子集;利用;

    margins    函數尚不能應用(作者還沒寫好),預計設定編輯匯總方向;

    fill    填充缺失值;

    drop    設置成FALSE顯示沒有聯合成功的行列

    value.var    填充值的列,默認會猜測

現在我需要取數據DT的v1,v2兩列相同的情況作為匯總的一類,對它們的v4值取平均,轉換如下,

              

                     轉換前                                                               轉換後

當然,上述過程也可以用data.table[ i , j , by ]語法做

 但是如果我要將上述DT中的v3作為一個影響因素,作為tag,先按v1、v2匯總,再將對應的v4值分為v3=1和v3=2兩類,查看v1、v2取值相同v3不同對應v4的情況,這個時候用dcast或者會更加方便,如下

 

 melt

    和reshape2包的melt一樣,融合表格,這個是用C語言寫的,處理速度更快。

處理前:

處理後:

 

    melt(data, id.vars, measure.vars,
        variable.name = "variable", value.name = "value",
        ..., na.rm = FALSE, variable.factor = TRUE,
        value.factor = FALSE,
        verbose = getOption("datatable.verbose"))

    data    data.table對象;

    id.vars    id變量組成的矢量,可以對應列號,也可以對應列名;缺失的話,非測量變量會被賦值;

    measure.vars    測量變量組成的是矢量或者列表,可以對應列號和列名,也支持pattern函數,下面會提到,如果缺失,非id變量會被賦值;如果measure.vars和id.vars都沒有賦予,全部非數字列會作為id.vars,剩余作為measure.vars;如果measure變量不是同一種類型,那麽會被強制轉換,等級如下list > character > numeric > integer > logical;

    variable.name    測量變量列名,默認"variable";

    value.name    融合後數據的數值列名;

    na.rm    如果TRUE,移除NA值;

    variable.factor    如果TRUE,變量列轉化為因子;

    verbose     如果TRUE,在工作臺產生交互信息,默認options(datatable.verbose=TRUE)

 

對於前面的DT,我現在將f和d開頭的列名的列作為測量變量,如下

 

 

pattern函數下面會講,這裏再講一下的是melt和dcast的聯合使用,先用melt融合,再用dcast重鑄

如下面例子

                                                     原DT

               

                               melt 後                                                                                                           再進行dcast後

 其實上述過程用data.table [ i , j , by ]語法也可以

看個人需要吧,各種各樣不同的方法都了解了以後,當你真正需要用到達到某個目的時,你的腦海裏就會自動匹配上最佳的處理方法。

 

patterns

    patterns是melt函數內部使用的函數,匹配正則表達式。melt的時候可以用正則去匹配列名

    patterns(..., cols=character(0))

    ...    正則表達式集;

    cols    要匹配的字符矢量;

    例子在講melt函數的時候已有

 

rbindlist

     類似於data.frame的rbind,不過比rbind的速度更快,並且總是返回data.table。也有不同之處,一是use.names參數,可以指定是否使用相同列名bind,二是rbindlist可以使用在不知道對象名字的情況下,比如lapply(fileNames, fread) 。

    rbindlist(l, use.names=fill, fill=FALSE, idcol=NULL)   

    l    對象列表,也可以分開寫

    use.names    如果TRUE, bind的時候匹配行名,默認FALSE,像rbind一樣,直接bind,當時TRUE的時候,至少要有一個對象的一列要存在行名;

    fill    如果TRUE,缺失的列用NA填充,這個時候bind的對象可以不同列數,並且use.names自動設為TRUE,這個時候至少要有一個對象的一列要存在行名;

    idcol    產生一個index列,默認(NULL)不產生,如果idcol=TRUE,行名自動為.id,當然你也可以直接命名,比如idcol="id";

 

  

between

    是data.table  i 語法的擴展功能,between等同於x >= lower 並且 x <= upper 當incbounds設置為TRUE的時候,設置為FALSE的時候則是x >= lower 並且 x <= upper

    between(x, lower, upper, incbounds=TRUE)
    x %between% y

    x    任意的可以排序的矢量,可以用"<="比較的

    lower    較低的範圍;

    upper    較高的範圍;

    y    長度為2的矢量或者列表,y[1] 相當於lower,y[2] 相當於upper;

    incbounds    如果TRUE意味著包括邊界,即<=或者>= ,默認TRUE;

    例如有基因組註釋文件如下

   

    我想取出在chr1上,start在16000到30000之間的geneID,可以用beween

 

 

foverlaps

    尋找重疊的區域,返回index對,x是數據很大但都是小區域的data.table,用來檢索,y是檢索用的資料,數據較小,都是大區域。

 

    foverlaps(x, y, by.x = if (!is.null(key(x))) key(x) else key(y),
        by.y = key(y), maxgap = 0L, minoverlap = 1L,
        type = c("any", "within", "start", "end", "equal"),
        mult = c("all", "first", "last"),
        nomatch = getOption("datatable.nomatch"),
        which = FALSE, verbose = getOption("datatable.verbose"))

    x,y    data.table,y需要設置key,x並不需要設置key;

    by.x,by.y    用來計算重疊的列名或者列號的矢量,by.x和by.y的最後兩列都應該對應各自的(x,y的)start和end區間列,並且start列應該總是小於end列,如果x設置了key ,by.x相當於key(x),否則by.x就默認key(y)。by.y默認key(y);

    maxgap    設定兩個區域空白區允許的最大值,參數尚不能使用;

    minoverlap    設定兩個區域最小的重疊區,參數尚不能使用;

    type    設置重疊類型。默認any。可以設置為any,within,start,end和equal。equal尚不能使用。假設x,y區間分別為[ a,b ]和[ c,d ] , start 要求a==c , end要求b==d , within要求 a>=c 並且b <= d , equal要求a==c,b==d, 如果是any的話,只要c<=b 並且d>=a 就可以了;

    mult    當y裏面的多行都匹配x裏面的行,mult=控制返回,默認all,也可以設置為"first”和last;

    nomatch    默認nomatch=NA,無匹配返回NA,也可以設置為0,0不返回該行;

    which    默認FALSE結果返回x和y行的聯合,當是TRUE時,如果mult=“all”,返回兩列,一列x列號,一列相對應的y,如果nomatch=NA,不匹配的返回y的NA,如果nomatch=0,則跳過該列,設置mult="first“,mult=”last"則最後返回x一樣的行數;

    verbose    當時TRUE的時候,工作臺交互

 

chmatch

     返回各字符串在第二個對象的首匹配位置,是match和%in%的加速版本。和fastmatch包的fmatch相比,各有優缺點。fmatch第一次匹配較慢,第二次匹配快,chmatch匹配雖然沒有fmatch第二次匹配快,但是首次匹配也有較快的速度。

    chmatch(x, table, nomatch=NA_integer_)
    x %chin% table
    x    字符矢量,需要去匹配的值;

    table    字符矢量,匹配的目標;

    nomatch    不匹配時返回的值,強制轉化整型

 

好了,寫到這裏寫的都有點累了,再介紹最後一個函數,有時候我們需要了解你寫的這個腳本運行所花費的時間,這個時候保存開始運行時間和結束運行時間,再進行相減之類的好像有點麻煩,其實我們可以用這個timetaken函數

timetaken

    timetaken(started.at)   

    started.at    proc.time( )的結果

    最好,寫完這篇博客,timetaken斷斷續續大約一星期

 

 

參考文獻

data.table manual:  https://cran.r-project.org/web/packages/data.table/data.table.pdf

 


Tags:

文章來源:


ads
ads

相關文章
ads

相關文章

ad