2015-06-08 22 views
2

我有三個數據幀,用了很多的信息和下面行名稱:共同要素框架

ENSG00000000971 ENSG00000000971 ENSG00000000971 
ENSG00000004139 ENSG00000004139 ENSG00000003987 
ENSG00000005001 ENSG00000004848 ENSG00000004848 
ENSG00000005102 ENSG00000002330 ENSG00000002330 
ENSG00000005486 ENSG00000005102 ENSG00000006047 
...    ...    ... 

我想要做的,就是找出所有的條目(列名)常見於至少有 2個數據幀。即,最終結果應該是單個列表,如下:

ENSG00000000971 
ENSG00000004139 
ENSG00000004848 
ENSG00000005102 
ENSG00000002330 

我該如何去做這件事?我試着這樣做:

shared.DESeq2.edgeR = data.frame(row.names(res.DESeq2) %in% row.names(res.edgeR)) 
shared.DESeq2.limma = data.frame(row.names(res.DESeq2) %in% row.names(res.limma)) 
shared.edgeR.limma = data.frame(row.names(res.edgeR) %in% row.names(res.limma)) 
shared = merge(merge(shared.DESeq2.edgeR, shared.DESeq2.limma), shared.edgeR.limma) 

...其中三個res.[DESeq2/edgeR/limma]是三個數據幀,但是這需要年齡運行(我甚至沒有讓它結束,所以我不知道,如果它實際上作品)。我有一些代碼爲所有三個數據幀共有的元素執行此操作,但我也對兩個或多個數據幀共有的元素感興趣,但我無法真正找到一個好方法去做這個。有任何想法嗎?

+0

任何數據幀都可以包含重複項嗎? –

+0

不,沒有任何數據框中的行名稱有重複。 – Sajber

回答

4

試試這個例子:

#dummy data, with real data we would do: res.DESeq2_rn <-row.names(res.DESeq2) 
res.DESeq2_rn <- letters[1:4] 
res.edgeR_rn <- letters[3:8] 
res.limma_rn <- letters[c(1,3,8,10)] 

#get counts 
res <- table(c(res.DESeq2_rn, res.edgeR_rn, res.limma_rn)) 
res 
# a b c d e f g h j 
# 2 1 3 2 1 1 1 2 1 

#result 
names(res)[ res>=2 ] 
#[1] "a" "c" "d" "h" 

編輯:基準測試表明通過@vaettchen解決方案是贏家!

library(microbenchmark) 
library(ggplot2) 
# create a large random character vector (this takes a lot of time!) 
set.seed(123) 
myNames <- sapply(1:1000000, 
        function(i)paste(sample(letters, 8, replace = TRUE), collapse = "")) 
A <- sample(myNames,1000) 
B <- sample(myNames,2000) 
C <- sample(myNames,3000) 

#benchmarking 3 options 
myBench <- microbenchmark(
    Which={ 
    res <- c(A,B,C) 
    out1 <- unique(res[ which(duplicated(res)) ]) }, 
    Table={ 
    res <- c(A,B,C) 
    y <- table(res) 
    out2 <- names(y)[ y >= 2 ] }, 
    Intersect={ 
    out3 <- 
     unique(
     c(intersect(A,B), 
      intersect(A,C), 
      intersect(B,C)))}, 
    times=1000) 

print(myBench) 
qplot(y=time, data=myBench, colour=expr) + scale_y_log10() 

Unit: microseconds 
     expr  min   lq  mean  median   uq  max neval cld 
    Which 266.837 280.4190 527.8266 288.2680 301.2475 59255.34 1000 a 
    Table 32167.286 32739.5945 34851.2260 33072.0825 33524.2550 108176.22 1000 b 
Intersect 450.965 472.3965 667.3316 484.7725 499.8650 60266.54 1000 a 

enter image description here

1

另一種方法,以@ zx8754的樣本數據:

# dummy data 
res.DESeq2 <- letters[ 1:4 ] 
res.edgeR <- letters[ 3:8 ] 
res.limma <- letters[ c(1, 3, 8, 10) ] 

# combine into one vector     
res <- c(res.DESeq2, res.edgeR, res.limma) 
res 
[1] "a" "b" "c" "d" "c" "d" "e" "f" "g" "h" "a" "c" "h" "j" 

# result 
unique(res[ which(duplicated(res)) ]) 
[1] "c" "d" "a" "h"     

編輯

@ zx8754的答案被接受,所有的很好的理由,它是乾淨和優雅。作爲純粹的我的求知慾的問題,我看着他和我的大樣本方法之間的性能差異,並發現它很有趣,足以將它張貼:

# create a large random character vector (this takes a lot of time!) 
res <- rep("x", 1000000) 
for(i in 1:1000000) 
    res[ i ] <- paste(sample(letters, 8, replace = TRUE), collapse = "") 
head(res) 
[1] "vsvkljgr" "ulxhqnas" "upqqtrdk" "pynuaihp" "srjtnvqm" "mxnlytvd" 

# vaettchen: 
system.time(x <- unique(res[ which(duplicated(res)) ])) 
user system elapsed 
0.173 0.000 0.171 
x 
[1] "zlzlwinb" "wielycpx" 

# zx8754 
system.time({ y <- table(res); z <- names(y)[ y >= 2 ] }) 
    user system elapsed 
18.945 0.020 19.058 
z 
[1] "wielycpx" "zlzlwinb" 

足夠大的數據或重複調用,所不同的可能很重要。什麼我的代碼的簡要說明做:

  • duplicated(res)創建一個包含邏輯TRUE或FALSE,取決於是否出現反覆
  • which(...)字符串長度資源的載體轉即到索引的矢量其中該值是TRUE
  • res[ ... ]提取在索引位置RE的實際字符值,和
  • unique(...)減小了每個字符值到僅一個的外觀,這是答案@Sajber一直在尋找(我理解)
+0

是的,基準測試表明你的方法是最快的。看到我編輯的帖子。 – zx8754