2015-05-15 68 views
4

我有一個大的表格式如下:[R總結數據幀具有獨特的功能

Data <- data.frame("Chrom" = c("chr1", "chr1", "chr1", "chr4", "chr4", "chr6"), "Site" = c(100, 200, 400, 140, 300, 400), "Heart" = c(20, 100, 0, 35, 92, 100), "Brain" = c(30, 40, 55, 100, 0, 100), "Liver" = c(100, 55, 20, 90, 0, 0), "Lungs" = c(100, 0, 80, 40, 30, 0)) 

,並提供:

> Data 
    Chrom Site Heart Brain Liver Lungs 
1 chr1 100 20 30 100 100 
2 chr1 200 100 40 55  0 
3 chr1 400  0 55 20 80 
4 chr4 140 35 100 90 40 
5 chr4 300 92  0  0 30 
6 chr6 400 100 100  0  0 

我想打一個數字與此類似公佈的數字。 (http://www.nature.com/ncomms/2015/150218/ncomms7363/fig_tab/ncomms7363_F1.html):

enter image description here

基本上每行(基於共同CHROM和網站),我想看看有多少中間值有。我在此將中間值定義爲15到85之間的值。然後,對於每個器官,我想知道在所有器官中有多少行是中間的,僅與該器官共有兩個器官或三個。

回答

4

顯示data.table的力量:

設置

library(data.table) 

Data <- data.frame("Chrom" = c("chr1", "chr1", "chr1", "chr4", "chr4", "chr6"), "Site" = c(100, 200, 400, 140, 300, 400), "Heart" = c(20, 100, 0, 35, 92, 100), "Brain" = c(30, 40, 55, 100, 0, 100), "Liver" = c(100, 55, 20, 90, 0, 0), "Lungs" = c(100, 0, 80, 40, 30, 0)) 

DT <- data.table(Data) 

isintermediate <- function(x){ 
    return(x >=15 & x <= 85) 
} 


DI <- DT[ , list(Chrom, Site, 
       Heart = isintermediate(Heart), 
       Brain = isintermediate(Brain), 
       Liver = isintermediate(Liver), 
       Lungs = isintermediate(Lungs))] 

這將創建一個矩陣DI看起來像:

> DI 
    Chrom Site Heart Brain Liver Lungs 
1: chr1 100 TRUE TRUE FALSE FALSE 
2: chr1 200 FALSE TRUE TRUE FALSE 
3: chr1 400 FALSE TRUE TRUE TRUE 
4: chr4 140 TRUE FALSE FALSE TRUE 
5: chr4 300 FALSE FALSE FALSE TRUE 
6: chr6 400 FALSE FALSE FALSE FALSE 

隨着TRUEFALSE如果一個值是否中間。 (可能比創建函數更快捷,但我覺得這種方法很容易遵循)。

計數中間體

現在,通過CHROM +網站計數中間值是簡單

# NoI is Number Intermediate 

> DI[, list(NoI = Heart + Brain + Liver + Lungs), by = c("Chrom","Site")] 
    Chrom Site NoI 
1: chr1 100 2 
2: chr1 200 2 
3: chr1 400 3 
4: chr4 140 2 
5: chr4 300 1 
6: chr6 400 0 

中間體計數由器官

對於中間橫跨的數目,這得到更復雜。

> DA 
    Chrom Site variable value 
1: chr1 100 Heart TRUE 
2: chr4 140 Heart TRUE 
3: chr1 100 Brain TRUE 
4: chr1 200 Brain TRUE 
5: chr1 400 Brain TRUE 
6: chr1 200 Liver TRUE 
7: chr1 400 Liver TRUE 
8: chr1 400 Lungs TRUE 
9: chr4 140 Lungs TRUE 
10: chr4 300 Lungs TRUE 

我們只是在真實值感興趣,因此[value == TRUE]

現在我們需要爲中間值的計數:首先,使用數據重塑

library(reshape2) 

DA <- melt(DI, id.vars = c("Chrom","Site"))[value == TRUE] 

這給融化每個站點,但附加到每個器官。我們可以用.Nby=要做到這一點,然後合併回到我們最初的表:

DA <- merge(DA,DA[, list(IAcc = .N), by = c("Chrom","Site")], by = c("Chrom","Site"))

,並提供:

> DA 
    Chrom Site variable value IAcc 
1: chr1 100 Heart TRUE 2 
2: chr1 100 Brain TRUE 2 
3: chr1 200 Brain TRUE 2 
4: chr1 200 Liver TRUE 2 
5: chr1 400 Brain TRUE 3 
6: chr1 400 Liver TRUE 3 
7: chr1 400 Lungs TRUE 3 
8: chr4 140 Heart TRUE 2 
9: chr4 140 Lungs TRUE 2 
10: chr4 300 Lungs TRUE 1 

現在所有剩下的是獲得獨特IAccs的計數通過各器官,我們可以用table功能得到:

Output <- data.table(table(DA[,list(variable,IAcc)])) 
> Output 
    variable IAcc N 
1: Heart 1 0 
2: Brain 1 0 
3: Liver 1 0 
4: Lungs 1 1 
5: Heart 2 2 
6: Brain 2 2 
7: Liver 2 1 
8: Lungs 2 1 
9: Heart 3 0 
10: Brain 3 1 
11: Liver 3 1 
12: Lungs 3 1 

IAcc是在同一個Chrom和Site上也具有中間值的器官(包括其本身)的數量,並且N是被看到的次數。

最後,繪製(原諒的默認顏色):

library(ggplot2) 

ggplot(Output, aes(x = variable, y = N, fill = IAcc)) + geom_bar(stat = "identity") 

enter image description here

+2

尼斯徹底的答案!對於'isintermediate'的重複應用,一種標準語法是使用'DT [,c(list(Chron),lapply(.SD,isintermediate)),。SDcols = yourcols]'。類似地,'NoI'可以是'Reduce(「+」,.SD)',使用相同的'yourcols'列名稱字符串。另外,fyi,melt將很快包含在data.table中,並且可以在github上的開發版本中找到(我認爲...我不使用它)。 – Frank

+2

@Frank'Reduce'看起來是正確的做法......並且同意使用'.SD',甚至可能更簡單:'DI < - DT [,lapply(.SD,isintermediate),by = c (「Chrom」,「Site」)]'SDcols可以隱含 – Chris

+0

非常好的答案!也像你的第一行;-)。 – Arun

2

對於你的問題的第一部分(每行找到多少箇中間值也有),你可以嘗試這樣的:

is_intermediate = function(x) { 
    return(x < 85 & x > 15) 
} 
res = sapply(Data[, 2:length(Data)], is_intermediate) 
rowSums(res) 

如果您熟悉dplyr + tidyr,你可以做類似於:

Data %>% gather(organ, value, Heart:lungs) %>% 
    group_by(Chrom, Site) %>% 
    summarise(n_intermediate = sum(is_intermediate(value))) 

這會給你每個Chrom/Site組合的中間值數量。

因爲你可以這樣做下一部分:

Data %>% select(-Chrom, -Site) %>% 
    mutate_each(funs(is_intermediate)) %>% 
    summarise_each(funs(sum)) 

這將讓你的中間值的數量由列。

+0

這是非常有益的,除了我仍然不知道如何總結的常用對每一個獨立的中間點的數目組織 – user2165857