2017-01-10 10 views
0

私はdata.tablesに新しいの一種だと私はこのようなDNAゲノム座標を含むテーブルを持っているの間違った金額を返します。行でdata.tableにカスタム関数を適用すると、値

 chrom pause strand coverage 
    1:  1 3025794  +  1 
    2:  1 3102057  +  2 
    3:  1 3102058  +  2 
    4:  1 3102078  +  1 
    5:  1 3108840  -  1 
    6:  1 3133041  +  1 

私はカスタムを書きました関数を2百万回の行テーブルの各行に適用するには、GenomicFeaturesのmapToTranscriptsを使用して、関連する2つの値を文字列と新しい座標の形式で取得します。私はこのように、二つの新しいコラムで私のテーブルにそれらを追加したい:

 chrom pause strand coverage  transcriptID CDS 
    1:  1 3025794  +  1 ENSMUST00000116652 196 
    2:  1 3102057  +  2 ENSMUST00000116652 35 
    3:  1 3102058  +  2 ENSMUST00000156816 888 
    4:  1 3102078  +  1 ENSMUST00000156816 883 
    5:  1 3108840  -  1 ENSMUST00000156816 882 
    6:  1 3133041  +  1 ENSMUST00000156816 880 

機能は以下の通りです:

get_feature <- function(dt){ 

     coordinate <- GRanges(dt$chrom, IRanges(dt$pause, width = 1), dt$strand) 
     hit <- mapToTranscripts(coordinate, cds_canonical, ignore.strand = FALSE) 
     tx_id <- tx_names[as.character(seqnames(hit))] 
     cds_coordinate <- sapply(ranges(hit), '[[', 1) 

     if(length(tx_id) == 0 || length(cds_coordinate) == 0) { 
     out <- list('NaN', 0) 
     } else { 
     out <- list(tx_id, cds_coordinate) 
     } 

     return(out) 
    } 

その後、私は:

counts[, c("transcriptID", "CDS"):=get_feature(.SD), by = .I] 

そしてI行ごとに1つの新しい要素ではなく、関数が元の表よりも短い2つのリストを返すことを示すこのエラーを取得します。

Warning messages: 
    1: In `[.data.table`(counts, , `:=`(c("transcriptID", "CDS"), ... : 
     Supplied 1112452 items to be assigned to 1886614 items of column 'transcriptID' (recycled leaving remainder of 774162 items). 
    2: In `[.data.table`(counts, , `:=`(c("transcriptID", "CDS"), ... : 
     Supplied 1112452 items to be assigned to 1886614 items of column 'CDS' (recycled leaving remainder of 774162 items). 

.I演算子を使用すると、行ベースで関数が適用され、行ごとに1つの値が返されると想定しました。ステートメントの場合、を使用して関数が空の値を返さないことを確認しました。

そしてIは、関数のこの模擬バージョン試み:

get_feature <- function(dt) { 

     return('I should be returned once for each row') 

    } 

および、このように呼ばれる:

new.table <- counts[, get_feature(.SD), by = .I] 

が、1つのつではなく、元の長さの、1行のデータテーブルを作成します。だから、私の機能、あるいは私がそれを呼んでいる方法は、何らかの形で結果のベクトルの要素を崩壊させていると結論づけました。私は間違って何をしていますか?

更新(溶液による): @StatLearnerが指摘したように、?data.tableで説明したように、ことthis answerに説明され、.Iのみ(DT[i,j,by=]のように)jにおける使用のために意図されています。従って、​​はby=NULLと等価であり、適切な構文はby=1:nrow(dt)であり、行番号ごとにグループ化し、関数を行ごとに適用する。

残念ながら、私の特定のケースでは、これは全く効率が悪く、100行で20秒の実行時間を計算しました。私の3,600万行のデータセットについて、完了までに3ヶ月かかる。

私の場合、私はあきらめてこのようなテーブル全体にmapToTranscripts関数を使用しなければなりませんでした。これは数秒かかり、明らかに意図された使用でした。

get_features <- function(dt){ 
     coordinate <- GRanges(dt$chrom, IRanges(dt$pause, width = 1), dt$strand) # define coordinate 
     hits <- mapToTranscripts(coordinate, cds_canonical, ignore.strand = FALSE) # map it to a transcript 
     tx_hit <- as.character(seqnames(hits)) # get transcript number 
     tx_id <- tx_names[tx_hit] # get transcript name from translation table 

     return(data.table('transcriptID'= tx_id, 
         'CDS_coordinate' = start(hits)) 
    } 

    density <- counts[, get_features(.SD)] 

私はdata.tablesを使用することができますので、その後GenomicFeaturesパッケージからmapFromTranscriptsを使用してバックゲノムへのマッピングは、私がやろうとしていたものの本来の目的であった、元のテーブルから情報を取得するために参加します。

答えて

3

データの各行に関数を適用する必要があるときのやり方。テーブルは、行番号によって、それをグループ化されている:

counts[, get_feature(.SD), by = 1:nrow(counts)] 

としては、this answerで説明し、それはグループ化することによって生成される行インデックスのシーケンスを返す必要があるため、.Ibyに使用するためのものではありません。 by = .Iがエラーをスローしない理由は、data.tableがdata.table名前空間にNULLというオブジェクト.Iを作成するため、by = .Iby = NULLに相当します。

require(data.table) 
counts <- data.table(chrom = sample.int(10, size = 100, replace = TRUE), 
        pause = sample((3 * 10^6):(3.2 * 10^6), size = 100), 
        strand = sample(c('-','+'), size = 100, replace = TRUE), 
        coverage = sample.int(3, size = 100, replace = TRUE)) 

get_feature <- function(dt){ 
    coordinate <- data.frame(dt$chrom, dt$pause, dt$strand) 
    rowNum <- nrow(coordinate) 
    return(list(text = 'Number of rows in dt', rowNum = rowNum)) 
} 

counts[, get_feature(.SD), by = 1:nrow(counts)] 

は、counts中と同じ行数とdata.tableを生成する:行番号によってby=1:nrow(dt)グループを使用して、関数がdata.tableのみから単一の行にアクセスすることを可能にすること

by = NULL関数に全体data.tableを供給しながら、しかしcoordinatecounts

nrow     text rowNum 
1: 1 Number of rows in dt  1 
2: 2 Number of rows in dt  1 
3: 3 Number of rows in dt  1 
4: 4 Number of rows in dt  1 
5: 5 Number of rows in dt  1 

からただ1つの行が含まれます

counts[, get_feature(.SD), by = NULL] 

        text rowNum 
1: Number of rows in dt 100 

byが機能するための方法です。

+0

良い答え@StatLearner。ようこそ! – rosscova

+0

これは本当に本当です、@StatLearner、私は 'by = NULL'でチェックし、結果は同じです。 'by = 1:NROW(dt)'を使うと、私の望むように関数が適用されますが、それは非常に遅いので、別の回避策を探す必要がありました。私はこの機能を私が望んでいた方法で使うことはできませんが、今日は 'data.tables'について多くのことを学んだので、どうもありがとう! –

+0

PS:面白いのは、[この他の回答]から「by = .I」というアイデアが得られたことです(http://stackoverflow.com/questions/25431307/r-data-table-apply-function-to-rows -using-columns-as-arguments)_ Google検索で表示される最初のものです_ "各行のデータテーブルに関数を適用" _。誰かが私と同じアイデアを持っている場合に備えて、そこに言及した答えをリンクします。 –

関連する問題