2016-03-16 2 views
1

У меня есть вектор в R:Как найти диапазоны последовательных чисел в векторе в R

data <- c(1,4,6,7,8,9,20,30,31,32,33,34,35,60) 

То, что я хочу, чтобы найти начало и конец последовательного участка больше, чем 3 последовательных значений. то есть:

start end 
3 6 (stretch 6-9) 
8 13 (stretch 30-35 

У меня нет понятия, как туда добраться.

+0

http://stackoverflow.com/questions/29184297/finding-the-start-and-stop-indices-in-sequence-in-r – Khashaa

+0

возможно, если вы посмотрите на 'rle()' и разницу в запаздывании. Если они являются последовательными значениями, разница в запаздывании будет равна 1. Посмотрите на последовательности из 1 в этом с помощью 'rle()' – cory

ответ

3

С @eddi's answer на мой аналогичный вопрос ...

runs = split(seq_along(data), cumsum(c(0, diff(data) > 1))) 
lapply(runs[lengths(runs) > 1], range) 

# $`2` 
# [1] 3 6 
# 
# $`4` 
# [1] 8 13 

Как это работает:

  • seq_along(data) являются показатели data из 1..length (данные)
  • c(0, diff(data) > 1) имеет 1 в каждом индексе, где data «прыжки»
  • cumsum(c(0, diff(data) > 1)) является идентификатором для последовательных прогонов между скачками

Так runs является подразделением data «S индексов в прогоны, где data» s значения являются последовательными.

+0

, это отличный ответ, если немного тонкое без сопроводительного объяснения – C8H10N4O2

+0

@ C8H добавлено, спасибо – Frank

+1

Чтобы сделать он выглядит как желаемый выход OP, вы можете сделать что-то вроде: 'df <- as.data.frame (do.call (rbind, lapply (run [lengths (running)> 1], range))); имена (df) <- c ("start", "end") ', хотя нужный результат явно не указан – C8H10N4O2

0

Итак, сначала возьмите diff и выполните последовательность длин последовательности. Тогда отправными точками являются индекс до 2s, а конечные точки - это отрицательные отличия от этих ... трудно объяснить, просто выполните код и проверьте его. Это не находит последовательности двух ... как (3,4) в (1, 3, 4, 7, 9). Я должен был включить часть remove для последовательностей, которые были отключены двумя ... (1, 3, 5, 7). Они не были пойманы правильно. Любое как, веселое упражнение. Я надеюсь, что кто-то сможет сделать лучше. Это немного беспорядок ...

data <- c(1,4,6,7,8,9,20,30,31,32,33,34,35,60) 
a <- sequence(rle(diff(data))$lengths) 
starts <- which(a==2) - 1 
ends <- which(diff(a)<0) + 1 
remove <- starts[starts %in% (ends-2)] 
starts <- starts[!starts %in% remove] 
ends <- ends[!ends %in% (remove+2)] 
if(length(ends) < length(starts)) ends <- c(ends, length(data)) 
> starts 
[1] 3 8 
> ends 
[1] 6 13 
> 
0

Вот основа R решение сильно полагаться на ?diff: ответ

data <- c(1,4,6,7,8,9,20,30,31,32,33,34,35,60) 

diff1 <- diff(data[1:(length(data)-1)]) # lag 1 difference 
diff2 <- diff(data, 2) # lag 2 difference 

# indices of starting consecutive stretches -- these will overlap 
start_index <- which(diff1==1 & diff2==2) 
end_index <- start_index + 2 

# notice that these overlap: 
data.frame(start_index, end_index) 

# To remove overlap: 
# We can remove *subsequent* consecutive start indices 
#   and *initial* consecutive end indices 

start_index_new <- start_index[which(c(0, diff(start_index))!=1)] 
end_index_new <- end_index[which(c(diff(end_index), 0) != 1)] 
data.frame(start_index_new, end_index_new) 

# start_index_new end_index_new 
# 1    3    6 
# 2    8   13 

Кори велик - это один может быть просто немного легче понять, потому что вы в основном проверяете случаи, когда с позиции i позиция i+1 имеет значение еще 1 и позиция i + 2 имеет значение 2. Вы строите диапазоны от этого, а затем объединяете диапазоны с другой функцией diff. По-моему, это немного проще.

Есть также пакеты, которые вы можете использовать как zoo, которые могут помочь вам получить разницу в качении.

Смежные вопросы