Как посчитать совпадения между вектором и данным кадра координат последовательности? - PullRequest
1 голос
/ 24 мая 2019

Дана таблица данных с начальными и конечными координатами для последовательностей целых чисел:

set.seed(1)

df1 <- data.table(
  START = c(seq(1, 10000000, 10), seq(1, 10000000, 10), seq(1, 10000000, 10)),
  END = c(seq(10, 10000000, 10), seq(10, 10000000, 10), seq(10, 10000000, 10)) 

И вектор целых чисел:

vec1 <- sample(1:100000, 10000)

Как подсчитать количество целых чисел в vec1, которые находятся в начальной и конечной координатах каждой последовательности в df1? В настоящее время я использую цикл for:

COUNT <- rep(NA, nrow(df1)) 
for (i in 1:nrow(df1)){
  vec2 <- seq(from = df1$START[i], to = df1$END[i])
  COUNT[i] <- table(vec2 %in% vec1)[2]
  print(i)
}
df1$COUNT <- COUNT

Однако данные и вектор, к которым я это применяю, очень велики? Кто-нибудь может предложить способ улучшить производительность?

Любая помощь будет принята с благодарностью!

Ответы [ 3 ]

2 голосов
/ 24 мая 2019

Один из вариантов - использовать between

library(data.table)
df1[, count := sum(between(vec1, START, END)), by = seq_len(nrow(df1))]
1 голос
/ 24 мая 2019

Мы можем сделать это с неэквивалентным объединением

df1[data.table(val = vec1),  count := .N,on = .(START < val,
      END >= val), by = .EACHI]
head(df1)

Если мы хотим получить вывод другим способом, используя пример @ minem

data.table(START = vec1, END = vec1)[df1, .N, 
       on = .(START >= START, END < END), by = .EACHI]
#   START END N
#1:     1   4 2
#2:     8   9 1
#3:    11  30 0
0 голосов
/ 24 мая 2019
### example data:
# df1 <- data.table(START = c(1, 8, 11), END = c(4, 9, 30))
# vec1 <- c(3, 2, 8)

#
df1[, ind := .I] # add uniqe index to data.table
dt2 <- as.data.table(vec1, key = 'vec1') # convert to data.table
dt2[, vec2 := vec1] # dublicate column
setkey(df1) # sets keys // order data by all columns
# Fast overlap join:
ans1 = foverlaps(dt2, df1, by.x = c('vec1', 'vec2'), by.y = c('START', 'END'),
                 type = "within", nomatch = 0L)

counts <- ans1[, .N, keyby = ind] # count by ind
# merge to inital data
df1[, COUNT := counts[df1, on = .(ind), x.N]]
df1

setorder(df1, ind) # reorder by ind to get inital order
df1[, ind := NULL] # deletes ind colum
df1[is.na(COUNT), COUNT := 0L] # NAs is 0 count
df1
#    START END COUNT
# 1:     1   4     2
# 2:     8   9     1
# 3:    11  30     0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...