Найдите ближайшие значения FALSE - PullRequest
0 голосов
/ 14 ноября 2018

Есть ли более элегантный способ решения этой проблемы?

Для каждого значения TRUE я ищу позиции ближайших предыдущих и следующих значений FALSE.

data:

vec <- c(FALSE, TRUE, TRUE, FALSE, TRUE, FALSE)

желаемый результат: (что-то вроде)

     pos start end
[1,] 2   1     4  
[2,] 3   1     4  
[3,] 5   4     6  

объяснение первая строка результата:

  • pos = 2, позиция первого ИСТИНЫ,
  • start = 1, позиция ближайшего FALSE перед pos = 2
  • end = 4, позиция ближайшего FALSE после pos = 2.

Уже работающее решение:

pos = which(vec)
f_pos = which(!vec)

t(
sapply(pos, function(x){ s <- rev(f_pos[f_pos < x])[1]; e <- f_pos[x < f_pos][1]; return(data.frame(pos = x, start = s, end = e)) })
)

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Использование findInterval

pos <- which(vec)
b <- which(!vec)

ix <- findInterval(pos, b)
cbind(pos, from = b[ix], to = b[ix + 1])
#      pos from to
# [1,]   2    1  4
# [2,]   3    1  4
# [3,]   5    4  6

Если мы немного растянем ваше «что-то вроде», простой cut подойдет:

data.frame(pos, rng = cut(pos, b))
#   pos   rng
# 1   2 (1,4]
# 2   3 (1,4]
# 3   5 (4,6]

Если вектор заканчивается на TRUE, решение findInterval выдаст NA в столбце 'to'. В cut последний «интервал» затем кодируется как NA.

0 голосов
/ 14 ноября 2018

Вы можете сделать так, как если бы FALSE определяли интервалы и использовать data.table::foverlaps, чтобы найти правильные:

library(data.table)

# put your objects in data.tables:
f_pos_inter <- data.table(start=head(f_pos, -1), end=tail(f_pos, -1))
pos_inter <- data.table(start=pos, end=pos)

# define the keys:
setkeyv(pos_inter, c("start", "end")); setkeyv(f_pos_inter, c("start", "end"))

res <- foverlaps(pos_inter, f_pos_inter)
#   start end i.start i.end
#1:     1   4       2     2
#2:     1   4       3     3
#3:     4   6       5     5

Вы можете дополнительно изменить порядок столбцов и оставить только те, которые вам нужны:

res[, i.end:=NULL]
setcolorder(res, c(3, 1, 2))
setnames(res, "i.start", "pos")
res
#   pos start end
#1:   2     1   4
#2:   3     1   4
#3:   5     4   6

NB: это даст NA в обоих столбцах start и end, если vec заканчивается TRUE

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...