如何查找列中与另一个数据帧范围匹配的单元格数?

时间:2016-01-14 07:45:30

标签: r dataframe

我有一个data.frame1,如:

Input_SNP_CHR   Input_SNP_BP     Set_1_CHR   Set_1_BP     Set_2_CHR   Set_2_BP     Set_3_CHR   Set_3_BP
    chr4         184648954        chr18      63760782       chr7      135798891      chr7        91206783  
    chr13        45801432         chr14      52254555       chr1      223293324      chr4        184648954
    chr18        71883393         chr22      50428069       chr7      138698825      chr18       63760782

我有另一个data.frame2,如:

CHR     BP1             BP2             Score   Value
chr1    29123222        29454711        -5.7648 599
chr13   45799118        45986770        -4.8403 473
chr5    46327104        46490961        -5.3036 536
chr6    50780759        51008404        -4.4165 415
chr18   63634657        63864734        -4.8096 469
chr1    77825305        78062178        -5.4671 559

我想知道data.frame1中每对中有多少行(一对是Input_SNP_CHR和Input_SNP_BP)两者匹配CHR并且落在data.frame2的BP1和BP2之间。例如,在我的第一对(Input_SNP对)中,我有一个匹配。这是第二行,其中Input_SNP的CHR(chr13)和BP(45801432)在data.frame2中与CHR(chr13)和BP范围(在45799118和45986770之间)的行匹配。对于我的第二对(Set_1对),我也有1个匹配(chr18),BP 63760782与chr18的第5行data.frame2和BP范围匹配。

我想要的输出是:

Input_SNP     Set_1     Set_2     Set_3
1             1         0         1

我将如何在R中执行此操作?

2 个答案:

答案 0 :(得分:2)

这是使用data.table的另一种可能的解决方案。首先我们将数据melt改为长格式,根据前Set列名称添加df列,然后将foverlapstable结合使用为了检查频率

library(data.table) # v 1.9.6+
Ldf <- melt(setDT(df), measure = patterns("CHR", "BP")) # Create a column for BP and CHR
Names <- unique(sub("(.*_.*)_.*", "\\1", names(df))) # Creates a sets names indx
setnames(Ldf[, variable := factor(Names[variable])], c("Set", "CHR", "BP1")) # Rename   
Ldf[, BP2 := BP1] # Creating right boundary for foverlaps
setkeyv(Ldf, names(Ldf)[-1]) # Keying for foverlaps
table(foverlaps(setDT(df2), Ldf, nomatch = 0L)$Set) # Running fovelaps and checking freqs 
# Input_SNP     Set_1     Set_2     Set_3 
#         1         1         0         1 

答案 1 :(得分:1)

我认为您的第一个data.frame中的数据应该格式化为

#       CHR      type        BP
# 1.1  chr4 Input_SNP 184648954
# 1.2 chr13 Input_SNP  45801432
# 1.3 chr18 Input_SNP  71883393
# 2.1 chr18     Set_1  63760782
# 2.2 chr14     Set_1  52254555
# 2.3 chr22     Set_1  50428069
# 3.1  chr7     Set_2 135798891
# 3.2  chr1     Set_2 223293324
# 3.3  chr7     Set_2 138698825
# 4.1  chr7     Set_3  91206783
# 4.2  chr4     Set_3 184648954
# 4.3 chr18     Set_3  63760782

(但行名不重要。)

理想情况下,您会生成类似的数据,但如果您已经按照自己提供的格式生成数据,则可以通过它进行转换(假设您的第一个数据的名称是df

type_list=lapply(strsplit(colnames(df),"_"),
                 function(x) c(paste0(x[1],"_",x[2])))

df_new=do.call("rbind",
               lapply(split(1:ncol(df),sort(rep(1:(ncol(df)/2),times=2))),
                      function(idxs) {
                        data.frame(CHR=df[,idxs[1]],
                                   type=type_list[[idxs[1]]],
                                   BP=df[,idxs[2]])}))

然后它只需要两行基础R来完成你的任务(假设第二个data.frame是df2

df_new_2=within(merge(df_new,df2,by="CHR"),
                cnt<-BP>=BP1&BP<=BP2)

sapply(split(df_new_2,df_new_2$type),function(x) sum(x$cnt))
#Input_SNP     Set_1     Set_2     Set_3 
#        1         1         0         1 

Set_3只有chr18只匹配一次。)