R:根据来自另一个data.table的条件“标记”一行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了R:根据来自另一个data.table的条件“标记”一行相关的知识,希望对你有一定的参考价值。

我有一个超过100,000行的data.table(A)。共有3列。

chrom start end 1: chr1 6484847 6484896 2: chr1 6484896 6484945 3: chr1 6484945 6484994 4: chr1 6484994 6485043 5: chr1 6485043 6485092 ---
183569: chrX 106893605 106893654 183570: chrX 106893654 106893703 183571: chrX 106893703 106893752 183572: chrX 106893752 106893801 183573: chrX 106893801 106894256

我想生成一个名为“gene”的新列,它为来自另一个data.table的每个行注释提供一个标签,该行有~90行(B)。见如下:

chrom start end gene 1: chr1 6484847 6521004 ESPN 2: chr1 41249683 41306124 KCNQ4 3: chr1 55464616 55474465 BSND 42: chrX 82763268 82764775 POU3F4 43: chrX 100600643 100603957 TIMM8A 44: chrX 106871653 106894256 PRPS1

如果data.table A中的行起始值在data.table B的行开始值和结束值内,则需要A中的行相应地标记正确的基因。

例如,得到的完整data.table A将是

chrom start end gene 1: chr1 6484847 6484896 ESPN 2: chr1 6484896 6484945 ESPN 3: chr1 6484945 6484994 ESPN 4: chr1 6484994 6485043 ESPN 5: chr1 6485043 6485092 ESPN ---
183569: chrX 106893605 106893654 TIMM8A 183570: chrX 106893654 106893703 TIMM8A 183571: chrX 106893703 106893752 TIMM8A 183572: chrX 106893752 106893801 TIMM8A 183573: chrX 106893801 106894256 TIMM8A

我已经尝试了一些嵌套循环来做这个,但这似乎需要花费太长时间。我认为必须有一种方法来使用data.table包,但我似乎无法弄明白。

任何和所有建议将不胜感激。

答案

虽然在基地R(或可能使用data.table)这样做肯定是可能的,但我强烈建议使用GenomicRanges;它是一个非常强大而灵活的R / Bioconductor库,专为这类任务而设计。

以下是使用GenomicRanges::findOverlaps的示例:

# Sample data
df1 <- read.table(text =
    "chrom     start      end
     chr1   6484847   6484896
     chr1   6484896   6484945
     chr1   6484945   6484994
     chr1   6484994   6485043
     chr1   6485043   6485092", sep = "", header = T, stringsAsFactors = F);

df2 <- read.table(text =
    "chrom     start       end     gene
     chr1   6484847   6521004     ESPN
     chr1  41249683  41306124     KCNQ4
     chr1  55464616  55474465     BSND
     chrX  82763268  82764775     POU3F4
     chrX 100600643 100603957     TIMM8A
     chrX 106871653 106894256     PRPS1", sep = "", header = TRUE, stringsAsFactors = F);

# Convert to GRanges objects
gr1 <- with(df1, GRanges(chrom, IRanges(start = start, end = end)));
gr2 <- with(df2, GRanges(chrom, IRanges(start = start, end = end), gene = gene));

# Find features from gr1 that overlap with gr2
m <- findOverlaps(gr1, gr2);

# Add gene annotation as metadata to gr1
mcols(gr1)$gene[queryHits(m)] <- mcols(gr2)$gene[subjectHits(m)];
gr1;
#GRanges object with 5 ranges and 1 metadata column:
#      seqnames             ranges strand |        gene
#         <Rle>          <IRanges>  <Rle> | <character>
#  [1]     chr1 [6484847, 6484896]      * |        ESPN
#  [2]     chr1 [6484896, 6484945]      * |        ESPN
#  [3]     chr1 [6484945, 6484994]      * |        ESPN
#  [4]     chr1 [6484994, 6485043]      * |        ESPN
#  [5]     chr1 [6485043, 6485092]      * |        ESPN
#  -------
#  seqinfo: 1 sequence from an unspecified genome; no seqlengths
另一答案

除了GRanges/IRanges solution by Maurits Evers之外,还有一种替代的data.table方法,使用非equi连接和连接更新。

A[B, on = .(chrom, start >= start, start <= end), gene := i.gene][]
    chrom     start       end  gene
 1:  chr1   6484847   6484896  ESPN
 2:  chr1   6484896   6484945  ESPN
 3:  chr1   6484945   6484994  ESPN
 4:  chr1   6484994   6485043  ESPN
 5:  chr1   6485043   6485092  ESPN
 6:  chrX 106893605 106893654 PRPS1
 7:  chrX 106893654 106893703 PRPS1
 8:  chrX 106893703 106893752 PRPS1
 9:  chrX 106893752 106893801 PRPS1
10:  chrX 106893801 106894256 PRPS1

根据OP,AB已经是data.table对象。因此,这种方法避免了对GRanges对象的强制。

Reproducible Data

library(data.table)
A <- fread("rn         chrom     start      end 
     1:  chr1   6484847   6484896 
     2:  chr1   6484896   6484945 
     3:  chr1   6484945   6484994 
     4:  chr1   6484994   6485043 
     5:  chr1   6485043   6485092
183569:  chrX 106893605 106893654
183570:  chrX 106893654 106893703
183571:  chrX 106893703 106893752
183572:  chrX 106893752 106893801
183573:  chrX 106893801 106894256", drop = 1L)

B <- fread("rn    chrom     start       end     gene
 1:  chr1   6484847   6521004     ESPN
 2:  chr1  41249683  41306124     KCNQ4
 3:  chr1  55464616  55474465     BSND
42:  chrX  82763268  82764775     POU3F4
43:  chrX 100600643 100603957     TIMM8A
44:  chrX 106871653 106894256     PRPS1", drop = 1L)

以上是关于R:根据来自另一个data.table的条件“标记”一行的主要内容,如果未能解决你的问题,请参考以下文章

R:如何在 data.table 中标记特定时间范围内的观察结果?

R在for循环中从data.table中提取元素[重复]

根据 R 中的条件创建重复行

根据另一个 data.table 中的值更新 data.table

r中最早的日期和ID的条件

R使用data.table中的条件查找波高于给定值的频率和持续时间