2015-10-29 6 views
2

Скажем, у меня есть набор данных, где последовательности длиной 1 являются незаконными, длина 2 законна, больше длины 5 являются незаконными, но разрешено прерывать более длинные последовательности до < = 5 последовательностей.Коды последовательности индексирования с использованием data.table

set.seed(1) 
DT1 <- data.table(smp = 1, R=sample(0:1, 20000, rep=TRUE), Seq = 0L) 
DT1[, smp:=1:length(smp)] 
DT1[, Seq:=seq(.N), by=list(cumsum(c(0, abs(diff(R)))))] 

Эта последняя линия идет непосредственно от: Creating a sequence in a data.table depending on a column

DT1[, fix_min:=ifelse((R==TRUE & Seq==1) | (R==FALSE), FALSE, TRUE)] 
fixmin_idx2 <- which(DT1[, fix_min==TRUE]) 
DT1[fixmin_idx2 -1, fix_min:=TRUE] 

Теперь мои длиной 2 правильно юридические дела отмечены. Разбейте> 5s.

DT1[R==1 & Seq==6, fix_min:=FALSE] 
DT1[,Seq2:=seq(.N), by=list(cumsum(c(0, abs(diff(fix_min)))))] 
DT1[R==1 & Seq2==6, fix_min:=FALSE] 
fixSeq2_idx7 <- which(DT1[,fix_min==TRUE] & DT1[,Seq2==7]) 
fixSeq2_idx7 
[1] 10203 13228 
DT1[fixSeq2_idx7,] 
smp R Seq fix_min Seq2 
1: 10203 1 13 TRUE 7 
2: 13228 1 13 TRUE 7 
DT1[fixSeq2_idx7 + 1,] 
smp R Seq fix_min Seq2 
1: 10204 1 14 TRUE 8 
2: 13229 0 1 FALSE 1 

И теперь, чтобы проверить, если SEQ2 == 7 сопровождается SEQ2 == 8, который был бы законным 2 длины. Я один 7, а затем 8 и один, за которым не следует 8. И там я застрял. Все, что я пробовал, либо устанавливает все fix_min в TRUE, либо чередует TRUE и FALSE.

Любое руководство очень ценится.

+0

Незначительное исправление: 'ifelse ((R == TRUE & Seq == 1) | (R == FALSE), FALSE, TRUE)' должно быть просто '! (R == 1 & Seq == 1) '. Обратите внимание, что 'R' равно 0/1, а не FALSE/TRUE.В другом месте я сильно подозреваю, что вам не нужно столько скобок. Например, в 'by =' вам не нужно обертывать один вектор в 'list()'. – Frank

+0

Не уверен, но дает ли это то, что вы ожидаете? 'DT1 [, if (.N> 1L) .SD [rep (seq_len (min (.N, 5L)), length.out = .N)], by =. (Rleid (R), R)]'. Он удаляет строки, где 'Seq' является просто' 1', а если '1: 9', он изменяет его на' 1: 5, 1: 4'. Это должно быть выполнено после первого блока кода. – Arun

+0

@Arun - Да, за исключением того, что я не хочу удалять строки в данных в этот момент, потому что нелегалы ​​представляют другое условие интереса к данным. – Chris

ответ

2

Если я правильно понял ваш вопрос, вы хотите установить fix_min на FALSE, если R == 0 или когда R == 1 & (1 =< Seq < 6 | Seq > 6). Тогда следующий должен дать вам то, что вы хотите:

# recreating the data from your first code block 
set.seed(1) 
DT1 <- data.table(R=sample(0:1, 20000, rep=TRUE))[, smp:=.I 
                ][, Seq:=seq(.N), by=rleid(R) 
                ][, Seq2 := Seq[.N], by=rleid(R)] 

# adding the needed 'fix_min' column 
DT1[, fix_min := (R==1 & Seq[.N] > 1 & Seq%%6!=0), by=rleid(R) 
    ][R==1 & Seq%%6==1 & Seq2%%6==1 & Seq==Seq2, fix_min := FALSE] 

Объяснение:

  • data.table(R=sample(0:1, 20000, rep=TRUE)) создает базу data.table
  • [, smp:=.I] создает индекс и добавляет его к данные.table
  • by=rleid(R) identifi последовательности; чтобы увидеть, что он делает: data.table(R=sample(0:1, 20000, rep=TRUE))[, seq.id:=rleid(R)]
  • [, Seq:=seq(.N), by=rleid(R)] создает индекс для каждой последовательности и добавляет его к data.table; последовательности обозначены rleid(R)
  • [, Seq2 := Seq[.N], by=rleid(R)] создает переменную, которая содержит значение, указывающее длину последовательности
  • fix_min := (R==1 & Seq[.N] > 1 & Seq%%6!=0) создает логический вектор с TRUE значений, где R==1 & длина последовательности больше, чем один (Seq[.N] > 1), за исключением значения, где номер последовательности является кратным 6 (Seq%%6!=0)
  • R==1 & Seq%%6==1 & Seq2%%6==1 & Seq==Seq2фильтрует data.table следующим образом: только те строки, где R==1 & sequ Значение ENCE является 7, 13, 19 и т.д. (Seq%%6==1) & длина последовательности 7, 13, 19, и т.д., и выбирает только последнюю строку (Seq==Seq2) из последовательностей, которые соответствуют другим условиям. С помощью fix_min := FALSE вы установите их на FALSE.
+0

Ну, нет. Если вы посмотрите на DT1 [19950: 20000], я вижу случай, начиная с 1998 года, который должен быть fix_min TRUE для 19989: 19993, FALSE за 19994, а затем TRUE за 1995: 19997. Именно поэтому в моем первоначальном подходе я решил снова индексировать Fix_min как Seq2, а не полагаться на Seq, хотя, честно говоря, могу сказать, что догадывался. – Chris

+0

@Chris Смотрите новое обновление. Для случаев, о которых вы упомянули, теперь дается правильный результат. Не могли бы вы проверить, хотите ли вы этого? – Jaap

+0

@ Jaap- Написание и визуальный осмотр Я обнаружил 21 случай заднего синглета 7 после 6 (2103/4.4834/5,5703/4,5802/3, 8468/9, 9275/6, 9956/7,10493/4,10822/3,11835/6,12618/9,13055/6, 13353/4,13551/2, 14308/9, 14423/4, 16389/90, 17449/50,17834/5, 19803/4), где 6 правильно установлено в ЛОЖЬ, и два случая 8869-8680, где разрешен второй прогон 6, и 13216-13228, где разрешен второй прогон 7, после установки 6 в FALSE. – Chris