Более быстрая функция вместо использования цикла for несколько раз при проверке конечных значений после сопоставления с индексами - PullRequest
0 голосов
/ 18 июня 2019

Я хочу сгенерировать двоичную переменную [0,1] с некоторым кодом, который работает быстрее, чем в примере ниже.Сценарий таков:

Если значение переменной mat $ misst равно единице (= 1) (то есть, когда C = 1 и B = 2011), я хочу проверить, есть ли какой-нибудь трейлинг "facitar "(в данном случае 5) значений равно нулю (= 0) и имеет такое же значение переменной A (A обозначает человека).в этом случае mat $ facit должен быть равен 1, в противном случае - нулю (0).

Мой код, приведенный ниже, работает, но набор данных, с которым я работаю, очень большой (8 000 000 строк), поэтому этот код требует возрастов...

A <- c(1,1,1,1,1,2,2,2,3,3,4,4,4,4,4,5,5,5,5,6,6,6,6)
B <- c(2011,2012,2013,2014,2015,2009,2010,2011,2009,2010,2009,2010,2011,2012,2013,2011,2012,2013,2014,2011,2012,2013,2014)
C <- c(1,1,1,1,99,0,1,0,1,1,0,0,1,0,0,1,1,1,99,1,1,1,0)
mat <- as.data.frame(cbind(A,B,C))

facitar <- 5

mat$misst <- ifelse((mat$C==1 & mat$B==2011),1,0)
mat$facit <- 0

### code with for loop

for(i in 1:nrow(mat)){
  if(mat$misst[i]==1){
    for(j in (i+1):(i+facitar)){
      if(mat$C[j]==0 & mat$A[j]==mat$A[i]){
        mat$facit[i] = 1
        break
      }
    }
  }
}

Я пытался работать с ifelse и apply, так как они (я думаю?) Работают более эффективно, но я так и не понял, как я могу получить тогдаработать так же, как для цикла.У кого-нибудь есть идея?Спасибо!

ДОБАВЛЕНИЕ (спасибо ZF007)

Вот попытка использования команды ifelse с функцией, содержащей цикл for (с, я думаю, будет использоваться простона значениях, где условие истинно), чтобы определить, задан ли элемент 0 или 1. Я не уверен, но если это может заставить работать, это может быть быстрее?или это совершенно неправильно?

mat$facit2 <- 0

func_facit <- function(){
  index_X01 <- which(mat$misst==mat$misst)
  for(j in (index_X01+1):(index_X01+facitar)){
    if(mat$C[j]==0 & mat$A[j]==mat$A[index_X01]){
      return(1)
      break
    } else{
      return(0)
    }
  }
}

mat$facit2 <- ifelse((mat$misst==1),func_facit,0)

Но здесь я получаю ошибку:

Error in rep(yes, length.out = length(ans)) : 
  attempt to replicate an object of type 'closure'

1 Ответ

0 голосов
/ 19 июня 2019

Вы можете использовать sapply и any, чтобы получить индексы для установки facit в 1

mat$facit[sapply(1:nrow(mat), function(i) {mat$misst[i]==1 && any(mat$C[i+1:facitar]==0 & mat$A[i+1:facitar]==mat$A[i])})] <- 1

Если вы хотите двоичную переменную, вы можете установить Фасит до TRUE или FALSE с:

mat$facit <- sapply(1:nrow(mat), function(i) {mat$misst[i]==1 && any(mat$C[i+1:facitar]==0 & mat$A[i+1:facitar]==mat$A[i])})
...