按类似行折叠数据框

时间:2015-01-14 15:54:19

标签: r bioinformatics collapse reshape

我想折叠以下数据框

DF

chr start    stop        gain loss pvalue_gain pvalue_loss
6 68838806   68857819    0    6    1.00000000  0.05105438
9 29779560   29788411    5    1    0.02320654  1.00000000
9 29788411   29809428    5    1    0.02320654  1.00000000
9 29809428   29831788    5    1    0.02320654  1.00000000
9 29831788   29899917    4    1    0.05145798  1.00000000
10   650294    727180    7    0    0.07759025  1.00000000

我想为每个chr折叠,其中连续行上的gain,loss,pvalue_gain和pvalue_loss数字相同。但是,对于折叠数据帧时的这些连续行,我想使用这些连续行的第一行中的起始编号和这些连续行中的最后一个停止编号。

例如 -

chr start    stop        gain loss pvalue_gain pvalue_loss
9 29779560   29788411    5    1    0.02320654  1.00000000
9 29788411   29809428    5    1    0.02320654  1.00000000
9 29809428   29831788    5    1    0.02320654  1.00000000

将折叠为

chr start    stop        gain loss pvalue_gain pvalue_loss
9 29779560   29831788    5    1    0.02320654  1.00000000

最终输出:

chr start    stop        gain loss pvalue_gain pvalue_loss
6 68838806   68857819    0    6    1.00000000  0.05105438
9 29779560   29831788    5    1    0.02320654  1.00000000
9 29831788   29899917    4    1    0.05145798  1.00000000
10   650294    727180    7    0    0.07759025  1.00000000

我不知道如何使用聚合函数执行此操作,并希望得到任何帮助。谢谢!

3 个答案:

答案 0 :(得分:5)

您可以使用unique包中的data.table进行一些修改:

library(data.table)
unique(as.data.table(df)[, stop := stop[.N], 
                           key = .(gain, loss, pvalue_gain, pvalue_loss)])

#    chr    start     stop gain loss pvalue_gain pvalue_loss
# 1:   6 68838806 68857819    0    6  1.00000000  0.05105438
# 2:   9 29831788 29899917    4    1  0.05145798  1.00000000
# 3:   9 29779560 29831788    5    1  0.02320654  1.00000000
# 4:  10   650294   727180    7    0  0.07759025  1.00000000

答案 1 :(得分:4)

你可以尝试

library(data.table)
setDT(df)[,list(chr=chr[1], start=start[1], stop=stop[.N]) ,
                 by=list(gain, loss, pvalue_gain, pvalue_loss)]

或使用dplyr

library(dplyr)
df %>% 
   group_by(gain, loss, pvalue_gain, pvalue_loss) %>% 
   summarise(chr=chr[1], start=start[1], stop=stop[n()])

更新

基于@Michael Lawrence关于非重叠比赛的评论,一种解决方法是:

setDT(df)[, .ind:= cumsum(c(TRUE,start[-1]!=stop[-.N])),
        list(gain, loss, pvalue_gain, pvalue_loss)][,
       list(chr=chr[1], start=start[1], stop=stop[.N]),
       list(gain, loss, pvalue_gain, pvalue_loss, .ind)][,.ind:=NULL][]
#    gain loss pvalue_gain pvalue_loss chr    start     stop
#1:    0    6       1.000       0.051   6 68838806 68857819
#2:    5    1       0.023       1.000   9 29779560 29831788
#3:    5    1       0.023       1.000   9 29831815 29831841
#4:    4    1       0.051       1.000   9 29831788 29899917
#5:    7    0       0.078       1.000  10   650294   727180

新数据

df <- structure(list(chr = c(6L, 9L, 9L, 9L, 9L, 9L, 10L), start = 
c(68838806L, 29779560L, 29788411L, 29809428L, 29831815L, 29831788L, 650294L
), stop = c(68857819L, 29788411L, 29809428L, 29831788L, 29831841L, 
29899917L, 727180L), gain = c(0L, 5L, 5L, 5L, 5L, 4L, 7L), loss = c(6L, 
1L, 1L, 1L, 1L, 1L, 0L), pvalue_gain = c(1, 0.02320654, 0.02320654, 
0.02320654, 0.02320654, 0.05145798, 0.07759025), pvalue_loss = c(0.05105438, 
1, 1, 1, 1, 1, 1)), .Names = c("chr", "start", "stop", "gain", 
"loss", "pvalue_gain", "pvalue_loss"), class = "data.frame", row.names = c(NA, 
-7L))

答案 2 :(得分:1)

由于您有基因组拷贝数数据,您可以考虑使用Bioconductor中的GenomicRanges包。您可以定义一个名为GRanges的对象,它正式表示数据的语义,因此能够为典型的用例提供方便有效的功能。

这里我们构造GRanges对象:

gr <- makeGRangesFromDataFrame(df)

现在我真正想要的是 ,只要拷贝数值相同,就会减少相邻范围。因此,我们只需要按照拷贝数值对数据进行分组:

grl <- split(gr, as.list(df[c("gain", "loss", "pvalue_gain", "pvalue_loss")]))

由于方法包中的错误,as.list是必需的。无论如何,我们然后减少相邻范围并继承值:

reduced <- unlist(reduce(grl))
values(reduced) <- values(unlist(phead(grl, 1L)))

最后一行有点复杂。如果GRangesList记得它是如何拆分的话会更好。现在正在努力。