A atualização direta (substituição) do quadro de dados esparsos é lenta e ineficiente

Estou tentando ler algumas centenas de milhares de arquivos JSON e, eventualmente, colocá-los em um objeto dplyr. Mas os arquivos JSON não são simples análises de valor-chave e exigem muito pré-processamento. O pré-processamento é codificado e é bastante bom em termos de eficiência. Mas o desafio que estou enfrentando é carregar cada registro em um único objeto (objeto data.table ou dplyr) com eficiência.

Estes são dados muito esparsos, terei mais de 2000 variáveis que estarão ausentes. Cada registro terá talvez cem variáveis definidas. As variáveis serão uma mistura de caracteres, lógicos e numéricos, eu sei o modo de cada variável.

Eu pensei que a melhor maneira de evitar R copiar o objeto para cada atualização (ou adicionar uma linha por vez) seria criar um quadro de dados vazio e, em seguida, atualizar os campos específicos após serem extraídos do arquivo JSON. Mas fazer isso em um quadro de dados é extremamente lento, passar para a tabela de dados ou objeto dplyr é muito melhor, mas ainda assim reduzi-lo a minutos em vez de horas. Veja meu exemplo abaixo:

timeMe <- function() {
  set.seed(1)
  names = paste0("A", seq(1:1200))

  # try with a data frame
  # outdf <- data.frame(matrix(NA, nrow=100, ncol=1200, dimnames=list(NULL, names)))
  # try with data table
  outdf <- data.table(matrix(NA, nrow=100, ncol=1200, dimnames=list(NULL, names)))

  for(i in seq(100)) {
    # generate 100 columns (real data is in json)
    sparse.cols <- sample(1200, 100)
    # Each record is coming in as a list
    # Each column is either a character, logical, or numeric
    sparse.val <- lapply(sparse.cols, function(i) {
      if(i < 401) {  # logical
        sample(c(TRUE, FALSE), 1) 
      } else if (i < 801) {  # numeric
        sample(seq(10), 1)
      } else { # character
        sample(LETTERS, 1)
      }
    })  # now we have a list with values to populate
    names(sparse.val) <- paste0("A", sparse.cols)

    # and here is the challenge and what takes a long time.
    # want to assign the ith row and the named column with each value
    for(x in names(sparse.val)) {
      val=sparse.val[[x]]
      # this is where the bottleneck is.
      # for data frame
      # outdf[i, x] <- val
      # for data table
      outdf[i, x:=val]
    }
  }  
  outdf
}

Eu pensei que o modo de cada coluna poderia ter sido definido e redefinido a cada atualização, mas também tentei isso predefinindo cada tipo de coluna e isso não ajudou.

Para mim, executar este exemplo com um data.frame (comentado acima) leva cerca de 22 segundos, a conversão para uma data.table é de 5 segundos. Eu esperava que alguém soubesse o que estava acontecendo nos bastidores e que pudesse fornecer uma maneira mais rápida de preencher a tabela de dados aqui.

questionAnswers(1)

yourAnswerToTheQuestion