パフォーマンスを向上させるために「サプライ」コマンドを書き直す方法は?
-
24-10-2019 - |
質問
〜1,300,000行と4列の「D」という名前のデータがあり、4列の4つの列と、〜12,000行と2列の「GC」という名前のフレームがあります(ただし、以下の小さな例を参照)。
d <- data.frame( gene=rep(c("a","b","c"),4), val=rnorm(12), ind=c( rep(rep("i1",3),2), rep(rep("i2",3),2) ), exp=c( rep("e1",3), rep("e2",3), rep("e1",3), rep("e2",3) ) )
gc <- data.frame( gene=c("a","b","c"), chr=c("c1","c2","c3") )
「D」がどのように見えるかは次のとおりです。
gene val ind exp
1 a 1.38711902 i1 e1
2 b -0.25578496 i1 e1
3 c 0.49331256 i1 e1
4 a -1.38015272 i1 e2
5 b 1.46779219 i1 e2
6 c -0.84946320 i1 e2
7 a 0.01188061 i2 e1
8 b -0.13225808 i2 e1
9 c 0.16508404 i2 e1
10 a 0.70949804 i2 e2
11 b -0.64950167 i2 e2
12 c 0.12472479 i2 e2
そして、ここに「GC」があります:
gene chr
1 a c1
2 b c2
3 c c3
「D」の最初の列と一致する「GC」からのデータを組み込むことにより、「D」に5列を追加したいと思います。今のところ私は使用しています さくらんぼ.
d$chr <- sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )
しかし、実際のデータでは、「非常に長い」時間がかかります(30分以上から「System.Time()」でコマンドを実行していますが、まだ終了していません)。
これを賢い方法で書き直す方法について何か考えがありますか?または、使用を検討する必要があります Plyr, 、たぶん「並列」オプションがあります(コンピューターに4つのコアがあります)?そのような場合、最高の構文は何ですか?
前もって感謝します。
解決
要因をインデックスとして使用できると思います。
gc[ d[,1], 2]
[1] c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3
Levels: c1 c2 c3
同じことをします:
sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )
[1] c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3
Levels: c1 c2 c3
しかし、はるかに速いです:
> system.time(replicate(1000,sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )))
user system elapsed
5.03 0.00 5.02
>
> system.time(replicate(1000,gc[ d[,1], 2]))
user system elapsed
0.12 0.00 0.13
編集:
私のコメントを少し拡大するために。 gc
データフレームには、の各レベルに1つの行が必要です gene
これが機能するレベルの順序で:
d <- data.frame( gene=rep(c("a","b","c"),4), val=rnorm(12), ind=c( rep(rep("i1",3),2), rep(rep("i2",3),2) ), exp=c( rep("e1",3), rep("e2",3), rep("e1",3), rep("e2",3) ) )
gc <- data.frame( gene=c("c","a","b"), chr=c("c1","c2","c3") )
gc[ d[,1], 2]
[1] c1 c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3
Levels: c1 c2 c3
sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )
[1] c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3 c1
Levels: c1 c2 c3
しかし、それを修正するのは難しくありません:
levels(gc$gene) <- levels(d$gene) # Seems redundant as this is done right quite often automatically
gc <- gc[order(gc$gene),]
gc[ d[,1], 2]
[1] c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3 c1
Levels: c1 c2 c3
sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )
[1] c2 c3 c1 c2 c3 c1 c2 c3 c1 c2 c3 c1
Levels: c1 c2 c3
他のヒント
Sashaのアプローチをタイミングで打ち負かすことはありませんが、より一般化可能で読みやすい代替ソリューションは、単に merge
2つのデータフレーム:
d <- merge(d, gc)
システムが遅いので、ここに私のタイミングがあります:
> system.time(replicate(1000,sapply( 1:nrow(d), function(x) gc[ gc$gene==d[x,1], ]$chr )))
user system elapsed
11.22 0.12 11.86
> system.time(replicate(1000,gc[ d[,1], 2]))
user system elapsed
0.34 0.00 0.35
> system.time(replicate(1000, merge(d, gc, by="gene")))
user system elapsed
3.35 0.02 3.40
利点は、複数のキー、一致しないアイテムを細かく制御できることなどです。
所属していません StackOverflow