Как заменить двойной цикл в R, когда необходимы определенные условия на линиях? - PullRequest
1 голос
/ 30 апреля 2019

В настоящее время я работаю над огромным файлом, содержащим остановки / ходы нескольких машин ( около 60 ) в течение длительного периода ( более 60 000 строк ). Я уже проиндексировал таблицу по 1, если устройство working, или 0, если оно not working.

**Date                     n°1    n°2    n°3    n°4    n°5   n°6    n°7**    

1  2011-12-13 00:00:00      0      1      1      1      1      1      1           
2  2011-12-13 01:00:00      0      1      1      1      1      1      1            
3  2011-12-13 02:00:00      0      1      1      1      1      1      1           
4  2011-12-13 03:00:00      0      1      1      1      1      1      1          
5  2011-12-13 04:00:00      0      1      1      1      1      1      1          
6  2011-12-13 05:00:00      0      1      1      1      1      1      1          
7  2011-12-13 06:00:00      0      1      1      1      1      1      1         

Иногда устройства должны быть остановлены (не одновременно) на более длительный период ( более 480 часов ) для определенных целей. Это эквивалентно более 480 последовательных неработающих рядов .

Я хотел бы определить эти конкретные периоды и отделить их от регулярных остановок 0 и заменить на -1, чтобы получить дату начала этих длинных периодов.

У меня уже работает код . Проблема в том, что запуск занимает много времени ... Я думаю, это из-за вложенного цикла. Но я попробовал и не могу найти другой способ обработки, например, с использованием lapply.

for (c in 2:ncol(dataframe)){
 for (r in 1:(nrow(dataframe)-480)) {
  if(sum(dataframe[r:(r+480),c])==0)     
  {dataframe[r,c]<-(-1) }
  else 
  {dataframe[r,c]<-dataframe[r,c]}
}}


for (c in 2:ncol(dataframe)){
 for (r in 1:(nrow(dataframe)-1)) {
  if (dataframe[r,c]==-1 && dataframe[r+1,c]==0)
  {dataframe[r+1,c]<-(-1)} 
}}

Этот код заменяет 0 на (-1), если в столбце есть не менее 480 следующих нулей. Если после нескольких последних нулей (последних) они будут преобразованы в «-1».

Я просто хотел бы знать, как я могу улучшить эту схему кодирования и сэкономить время вычислений ...

Заранее спасибо

1 Ответ

2 голосов
/ 30 апреля 2019

Для этого вы можете использовать rle (спасибо @ A.Suliman за полезный комментарий).

f <- function(x, thres = 480, replacement = -1) {
  r <- rle(x)
  r$values <- with(r, replace(values, lengths >= thres & values == 0, replacement))
  inverse.rle(r)
}

Примените функцию к каждому столбцу, я использую 5 последовательных 0 в качестве примера.(вам нужно исключить первый столбец и установить thres = 480, то есть dat[-1] <- lapply(dat[-1], f))

dat[] <- lapply(dat, f, thres = 5)
dat
#   X1 X2 X3 X4 X5 X6 X7
#1   0  1  1  1  0  0  1
#2   0 -1  0 -1  1  0  0
#3   0 -1  1 -1  0  0  0
#4   1 -1  0 -1  0  1  0
#5   0 -1  0 -1  1  0  1
#6   1 -1  1 -1  0  0 -1
#7   1 -1  0 -1  1  0 -1
#8  -1 -1  0  1 -1  0 -1
#9  -1  1  1  0 -1  1 -1
#10 -1 -1  0  1 -1  0 -1
#11 -1 -1  0  0 -1  1 -1
#12 -1 -1  1  1 -1  1 -1
#13 -1 -1 -1  0 -1  0 -1
#14 -1 -1 -1  0  1  0 -1
#15  1  1 -1  0  1  0  1
#16  0  0 -1  1  1  0  0
#17  1  1 -1  1  0  1  0
#18  1  0 -1  0  0  0  0
#19  0  1 -1  1  1  0  1
#20  1  0 -1  1  0  0  0

data

set.seed(1)
dat <- data.frame(replicate(7, expr = sample(c(0, 1), 20, TRUE, prob = c(.7, .3))))
...