Eu tenho um grande data.table , com muitos valores ausentes espalhados por suas ~ 200k linhas e 200 colunas. Gostaria de codificar novamente esses valores de NA para zeros da maneira mais eficiente possível.
Eu vejo duas opções:
1: Converter em um data.frame e usar algo como este
2: Algum tipo de comando legal de subconfiguração data.table
Ficarei feliz com uma solução bastante eficiente do tipo 1. A conversão para um data.frame e depois para uma tabela de dados não levará muito tempo.
r
performance
dataframe
data.table
Zach
fonte
fonte
data.table
para umdata.frame
? Adata.table
é adata.frame
. Qualquer operação data.frame simplesmente funcionará.data.table
especificando o número da coluna. entãoDT[,3]
não dará a terceira coluna. acho que isso inviabiliza a solução proposta no link aqui. Tenho certeza de que existe uma abordagem elegante usando algumasdata.table
magias!DT[, 3, with=FALSE]
retorna a terceira coluna.mydf[is.na(mydf) == TRUE]
é que o trabalho em quadros de dados, ao mesmo tempomydt[is.na(mydt) == TRUE]
dá-me algo estranho mesmo que eu usowith=FALSE
Respostas:
Aqui está uma solução usando o operador data.table
:=
, com base nas respostas de Andrie e Ramnath.Observe que f_dowle atualizou o dt1 por referência. Se uma cópia local for necessária, será necessária uma chamada explícita para a
copy
função para fazer uma cópia local de todo o conjunto de dados. de data.tablesetkey
,key<-
e:=
não copiar-on-write.A seguir, vamos ver onde f_dowle está gastando seu tempo.
Lá, eu focaria
na.replace
eis.na
, onde existem algumas cópias e digitalizações de vetores. Esses podem ser facilmente eliminados escrevendo uma pequena função C na.replace que atualizaNA
por referência no vetor. Pelo menos isso reduziria pela metade os 20 segundos. Essa função existe em algum pacote R?O motivo da
f_andrie
falha pode ser porque ele copia o conjunto inteirodt1
ou cria uma matriz lógica do tamanho do conjuntodt1
algumas vezes. Os outros 2 métodos funcionam em uma coluna de cada vez (embora eu tenha olhado brevementeNAToUnknown
).EDIT (solução mais elegante conforme solicitado por Ramnath nos comentários):
Eu gostaria de fazê-lo dessa maneira para começar!
EDIT2 (mais de um ano depois, agora)
Há também
set()
. Isso pode ser mais rápido se houver muitas colunas em loop, pois evita a sobrecarga (pequena) da chamada[,:=,]
em um loop.set
é um loopable:=
. Veja?set
.fonte
eval(parse)...
material. em uma nota mais ampla, acho que seria útil ter operações que funcionem em todos os elementos dodata.table
.data.table
maneira mais apropriada de fazer isso. Obrigado!DT
tem colunas do tipological
, ao contrário docreate_dt()
exemplo para este teste. Altere o quarto argumento daset()
chamada (que está0
no seu exemplo e digite duas vezes em R) paraFALSE
e deve funcionar sem aviso.seq_along(DT)
também prefiro . Mas então o leitor precisa saber queseq_along
seria ao longo das colunas e não nas linhas.seq_len(col(DT))
um pouco mais explícito por esse motivo.Aqui está o mais simples que eu poderia criar:
dt[is.na(dt)] <- 0
É eficiente e não há necessidade de escrever funções e outros códigos de cola.
fonte
[.data.table
(dt, is.na (dt)): i é do tipo inválido (matriz). Talvez no futuro uma matriz de 2 colunas possa retornar uma lista de elementos de TD (no espírito de A [B] na FAQ 2.14). Informe a ajuda da tabela de dados se você gostaria disso ou adicione seus comentários à FR # 657. >set
Funções dedicadas (
nafill
esetnafill
) para esse fim estão disponíveis nodata.table
pacote (versão> = 1.12.4):Ele processa colunas em paralelo tão bem que aborda os benchmarks publicados anteriormente, abaixo do tempo em relação à abordagem mais rápida até agora, e também ampliou, usando uma máquina de 40 núcleos.
fonte
Apenas para referência, mais lento em comparação com gdata ou data.matrix, mas usa apenas o pacote data.table e pode lidar com entradas não numéricas.
fonte
ifelse
e atualizar por referência fazendo issoDT[, names(DT) := lapply(.SD, function(x) {x[is.na(x)] <- "0" ; x})]
. E duvido que seja mais lento que as respostas que você mencionou.Aqui está uma solução usando
NAToUnknown
nogdata
pacote. Usei a solução da Andrie para criar uma enorme tabela de dados e também incluí comparações de tempo com a solução da Andrie.fonte
user
mas realmente há uma grande diferença noelapsed
tempo.rbenchmark
para comparar soluções usando mais replicações, mas obtive um erro de falta de memória, possivelmente devido ao tamanho do quadro de dados. se você pode executarbenchmark
em ambas estas soluções com várias repetições, esses resultados seria interessante como eu não sou realmente certo porque eu estou recebendo um aumento de velocidade 3xncol=5
eu acho (deve levar muito mais tempo) devido ao errocreate_dt
.Por uma questão de completude, outra maneira de substituir NAs por 0 é usar
Para comparar resultados e tempos, incorporei todas as abordagens mencionadas até agora.
Portanto, a nova abordagem é um pouco mais lenta do que
f_dowle3
mas mais rápida que todas as outras abordagens. Mas, para ser sincero, isso é contrário à minha intuição da sintaxe data.table e não tenho idéia do por que isso funciona. Alguém pode me esclarecer?fonte
Meu entendimento é que o segredo para operações rápidas em R é utilizar vetores (ou matrizes, que são vetores sob o capô).
Nesta solução, uso um
data.matrix
que é um,array
mas se comporta um pouco como umdata.frame
. Por ser uma matriz, você pode usar uma substituição de vetor muito simples para substituir osNA
s:Uma pequena função auxiliar para remover os
NA
. A essência é uma única linha de código. Eu só faço isso para medir o tempo de execução.Uma pequena função auxiliar para criar um
data.table
tamanho específico.Demonstração em uma pequena amostra:
fonte
remove_na
. Esse tempo de 21.57s inclui ocreate_dt
(incluindorunif
esample
) junto com oremove_na
. Alguma chance de você editar para dividir as duas vezes?create_dt
? Parece para criar sempre um data.table 5 coluna independentemente doncol
passado.Para generalizar para muitas colunas, você pode usar essa abordagem (usando dados de amostra anteriores, mas adicionando uma coluna):
Mas não testou a velocidade
fonte
fonte
Usando a
fifelse
função dasdata.table
versões mais recentes 1.12.6, é até 10 vezes mais rápido queNAToUnknown
nogdata
pacote:fonte
f_dowle3
ainda será mais rápido: stackoverflow.com/a/7249454/345660