首页 > 解决方案 > 如何计算与给定数据表匹配的序列分数与开始和结束坐标?

问题描述

给定两个数据表,其中包含整数序列的开始坐标和结束坐标:

df1 <- data.table(CAT = c(rep("A", 3), rep("B", 3), rep("C", 3)),
              START = c(1, 11, 21, 1, 21, 41, 1, 11, 21),
              END = c(10, 20, 30, 20, 40, 60, 10, 20, 30)
)
df2 <- data.table(CAT = c(rep("A", 3), rep("B", 3), rep("C", 3)),
              START = c(1, 11, 21, 31, 41, 51, 1, 11, 21),
              END = c(5, 17, 23, 38, 48, 54, 9, 17, 26)
)

如何计算每个序列中的整数个数,这些整数在匹配df1的任何序列的开始和结束坐标内?我目前正在使用 for 循环:df2CAT

seq2 <- Vectorize(seq.default, vectorize.args = c("from", "to"))
df1$MATCH <- NA
for (i in 1:nrow(df1)){
  df2_sub <- subset(df2, df2$CAT == df1$CAT[i])
  df2_int <- unlist(seq2(from = df2_sub$START, to = df2_sub$END))
  df1_int <- seq(df1$START[i], df1$END[i])
  df1$MATCH[i] <- length(na.omit(match(df1_int, df2_int)))
}

返回

df1
   CAT START END MATCH
1:   A     1  10     5
2:   A    11  20     7
3:   A    21  30     3
4:   B     1  20     0
5:   B    21  40     8
6:   B    41  60    12
7:   C     1  10     9
8:   C    11  20     7
9:   C    21  30     6

但是,我应用它的数据表和向量非常大?有人能提出提高性能的方法吗?也许使用data.table

标签: rperformancedata.tablesequencematching

解决方案


无需创建之后折叠的序列。

正如Cole所提到的,该foverlaps()函数可用于识别重叠序列。通过一些简单的算术,可以计算重叠的长度,这些重叠的长度是为 的每一行聚合的df1,最后:

library(data.table)
foverlaps(df1[, rn := .I], setkey(df2, CAT, START, END))[
  , ovl := (pmin(END, i.END) - pmax(START, i.START) + 1)][
    , .(MATCH = sum(ovl)), by = .(rn)][
      is.na(MATCH), MATCH := 0][]
   rn MATCH
1:  1     5
2:  2     7
3:  3     3
4:  4     0
5:  5     8
6:  6    12
7:  7     9
8:  8     7
9:  9     6

1.12.3的开发版本data.table自带一个新nafill()功能:

library(data.table) # version 1.12.3
foverlaps(df1[, rn := .I], setkey(df2, CAT, START, END))[
  , ovl := (pmin(END, i.END) - pmax(START, i.START) + 1)][
    , .(MATCH = sum(ovl)), by = .(rn)][
      , MATCH := nafill(MATCH, fill = 0)][]

推荐阅读