2015-09-30 3 views
4

У меня есть df, и я хотел бы извлечь все строки на основе следующих сигналов начала и конца.Как извлечь все строки между сигналом начала и конечным сигналом?

Сигнал запуска: при изменении состояния от 1 до 0 Конечный сигнал: при изменении состояния от 0 до -1.

df <- data.frame(time = rep(1:14), status = c(0,1,1,0,0,0,-1,0,1,0,0,0,-1,0)) 

    time status 
1  1  0 
2  2  1 
3  3  1 
4  4  0 
5  5  0 
6  6  0 
7  7  -1 
8  8  0 
9  9  1 
10 10  0 
11 11  0 
12 12  0 
13 13  -1 
14 14  0 

Желание:

time status  
4  4  0 
5  5  0 
6  6  0 
10 10  0 
11 11  0 
12 12  0 
+1

Сигнал пуска определяется, когда состояние изменяется от 1 до 0, а конечный сигнал имеет значение от 0 до -1. Итак, в этом примере я хотел бы получить все строки от 4 до 6 и от 10 до 12. – amyotun

ответ

2

Мы считаем метки начала и конца, а затем использовать эти значения и кумулятивную-сумму (старт - конец) для фильтрации строк. (cumsum(start)-cumsum(end)>1) - это небольшая скрипка, позволяющая избежать кумулятивных подсчетов, начиная с строки 2, которая начинается, но не заканчивается; иначе строка 14 будет нежелательно включена.

require(dplyr) 

df %>% mutate(start=(status==1), end=(status==-1)) %>% 
     filter(!start & !end & (cumsum(start)-cumsum(end)>1)) %>% 
     select(-start, -end) 

# time status 
# 1 4  0 
# 2 5  0 
# 3 6  0 
# 4 10  0 
# 5 11  0 
# 6 12  0 
+1

@ Давид Аренбург: у этого есть все, что связано с указанным вопросом ** «извлечь все строки, когда status = 1 в качестве сигнала запуска, а статус = -1 в качестве конечного сигнала» **. Затем ОП полностью меняет вопрос в комментарии, добавленном в вопрос. Прошу прощения. – smci

+1

OP хочет извлечь все строки между последовательностью 1 и -1, выглядит очень ясно для меня. –

+0

@DavidArenburg: ** «Я хотел бы извлечь все строки, когда status = 1 в качестве стартового сигнала и status = -1 в качестве конечного сигнала» ** буквально запрашивает все строки со статусом == +1 или -1. Понятно, что это не то, что они имели в виду. Как я уже писал выше, я пересматриваю свой код на основе повторного вопроса OP. – smci

1

Немного некрасиво, но вы всегда можете просто перебираем значения и держать флаг для определения того, следует ли элемент быть или нет.

keepers <- rep(FALSE, nrow(df)) 
flag <- FALSE 
for(i in 1:(nrow(df)-1)) { 
    if(df$status[i] == 1 && df$status[i+1] == 0) { 
     flag <- TRUE 
     next # keep signal index false 
    } 
    if(df$status[i] == -1 && df$status[i+1] == 0) { 
     flag <- FALSE 
     next # keep signal index false 
    } 
    keepers[i] <- flag 
} 
keepers[nrow(df)] <- flag # Set the last element to final flag value 
newdf <- df[keepers, ] # subset based on the T/F values determined 
6

Это возможное решение с использованием пакета data.table. Я в основном первая группировка по status == 1 выступлениям, а затем проверить в группу, если существует также status == -1, если да, то я к югу не устанавливая группу из второго инцидента до -1 инцидента минус 1

library(data.table) 
setDT(df)[, indx := cumsum(status == 1)] 
df[, if(any(status == -1)) .SD[2:(which(status == -1) - 1)], by = indx] 
# indx time status 
# 1: 2 4  0 
# 2: 2 5  0 
# 3: 2 6  0 
# 4: 3 10  0 
# 5: 3 11  0 
# 6: 3 12  0 
1

Do у вас есть еще несколько данных (или вы можете узнать больше о данных, которые вы знаете из результатов), чтобы узнать, являются ли эти/эти обобщения?

Два подобного подход:

library(stringr) 

df <- data.frame(time = rep(1:14), status = c(0,1,1,0,0,0,-1,0,1,0,0,0,-1,0)) 

dfr <- rle(df$status) 

# first approach 

find_seq_str <- function() { 
    str_locate_all(paste(gsub("-1", "x", dfr$values), collapse=""), "10")[[1]][,2] 
} 

df[as.vector(sapply(find_seq_str(), 
    function(n) { 
    i <- sum(dfr$lengths[1:(n-1)]) 
    tail(i:(i+dfr$lengths[n]), -1) 
    })),] 


# second approach 

find_seq_ts <- function() { 
    which(apply(embed(dfr$values, 2), 1, function(x) all(x == c(0, 1)))) 
} 

df[as.vector(sapply(find_seq_ts(), 
    function(n) { 
    i <- sum(dfr$lengths[1:(n)])+1 
    head(i:(i+dfr$lengths[n+1]), -1) 
    })),] 

Оба подхода нуждается в длину перспективы кодировании status вектора.

Первый делает один символ замену для -1 поэтому мы можем сделать однозначную, прилегающая строку затем использовать str_locate, чтобы найти пары, которые говорят нам, когда целевая последовательность начинается тогда перестраивает диапазоны нулей от длины RLE.

Если это должно быть база R, я могу попытаться взломать что-то с помощью regexpr.

Вторая строит парную матрицу и сравнивает ее с той же целевой последовательностью.

Предостережения:

  • Я не сделал никакого сравнительного анализа
  • Оба создают потенциально большие вещи, если status большой.
  • Я не полностью уверен, что он обобщает (отсюда и мой начальный q).
  • Дэвид является гораздо более удобным для чтения, ремонтопригодны & передаваемом код, но вы получите, чтобы иметь дело со всеми «благости», который приходит с использованием data.table ;-)

Я завернул подходы в функциях, поскольку они потенциально могут быть затем параметризуется, но вы можете просто просто присвоить значение переменной или вставить ее в sapply (тьфу, тo).

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