Add row by row in a data.table in R

7

Is there any method that can be added row by row in a data.table in R without needing to use a 'for', so that the value of the next row in a column is the value of the previous row added with a different value for each line?

Trying to solve a polling exercise in R, I came across the following problem: I have a data.table with a column with the first value equal to 50 and the remainder 0 (10 ^ 6 lines), and the other column contains -1 or 1, corresponding to adding or subtracting 1 from that initial number. However, after adding or subtracting, it can not be less than zero or greater than 100.

# Valores iniciais:
N <- 100             # Número total de bolas
nRetiradas <- 1e6   # Número de inteirações (retiradas) do problema
q <- 0.35            # Probabilidade de transferência para urna com n <= N/2
p <- 1.0 - q           # Probabilidade de transferência para urna com n > N/2

# A tabela urnas[] armazena o número de bolas em cada passo em cada retirada
urnas <- data.table(A <- rep(0, nRetiradas), B <- rep(0, nRetiradas))
setnames(urnas, names(urnas), c("A", "B"))
rm(A, B)

# Condição inicial das urnas A e B:
urnas$A[[1]] <- N/2
urnas$B[[1]] <- N/2

# Escolha aleatória: considero que 1 represente uma bola retirada de uma urna
# com n > N/2, e -1 para uma urna com n <= N/2. Gero uma sequência inicial 
# para uma das urnas e multiplico esta por -1 para a outra urna
retiradas_A <- ifelse(runif(nRetiradas)<q,-1,1)
retiradas_B <- (-1)*retiradas_A

foreach(i=2:nRetiradas) %do% {
  if(min(urnas$A[[i-1]] + retiradas_A[i], urnas$B[[i-1]] + 
         retiradas_B[i]) >= 0){
    urnas$A[[i]] <- urnas$A[[i-1]] + retiradas_A[i]
    urnas$B[[i]] <- urnas$B[[i-1]] + retiradas_B[i]    

  } else {
    urnas$A[[i]] <- urnas$A[[i-1]] + retiradas_B[i]
    urnas$B[[i]] <- urnas$B[[i-1]] + retiradas_A[i]   
  }
}

As I've implemented, each line of data.table will depend on the previous line, so I was only able to resolve using a very long delay. But to traverse 10 ^ 6 lines of the data.table is delaying horrors. Is there any more efficient solution? (even if it involves totally modifying my approach)

    
asked by anonymous 25.06.2017 / 09:03

1 answer

1

I was able to greatly optimize execution using arrays instead of data.table (there was nothing in my program that justified the need for a data.table).

Here is the solution code I found:

# Valores iniciais:
N <- 100             # Número total de bolas
nRetiradas <- 1e6   # Número de inteirações (retiradas) do problema
nDescarte <- 1e4    # Número de descartes no início da sequência
q <- 0.35            # Probabilidade de transferência para urna com n <= N/2
p <- 1.0 - q           # Probabilidade de transferência para urna com n > N/2

# A tabela urnas[] armazena o número de bolas em cada passo em cada retirada
urnas <- matrix(data = NA, nrow = nRetiradas, ncol = 2)

# Condição inicial das urnas A e B:
urnas[1,1] <- N/2
urnas[1,2] <- N/2

# Escolha aleatória: considero que 1 represente uma bola retirada de uma urna
# com n > N/2, e -1 para uma urna com n <= N/2. Gero uma sequência inicial 
# para uma das urnas e multiplico esta por -1 para a outra urna
retiradas_A <- ifelse(runif(nRetiradas)<q,-1,1)
retiradas_B <- (-1)*retiradas_A

tempoInicio <- Sys.time()

# foreach é um comando para realizar um laço 'for' utilizando 
# paralelismo entre os multiplos Cores disponíveis no hardware.
for(i in 2:nRetiradas) {
  if(min(urnas[i-1, 1] + retiradas_A[i], urnas[i-1,2] + 
         retiradas_B[i]) >= 0){
    urnas[i,1] <- urnas[i-1,1] + retiradas_A[i]
    urnas[i,2] <- urnas[i-1,2] + retiradas_B[i]    

  } else {
    urnas[i,1] <- urnas[i-1, 1]+ retiradas_B[i]
    urnas[i,2] <- urnas[i-1, 2] + retiradas_A[i]   
  }
}

I hope at some point this can help anyone who comes across a similar problem!

    
26.06.2017 / 22:52