Visão geral
Estou relativamente familiarizado data.table
, não muito dplyr
. Eu li algumas dplyr
vinhetas e exemplos que apareceram no SO, e até agora minhas conclusões são as seguintes:
data.table
edplyr
são comparáveis em velocidade, exceto quando existem muitos grupos (ou seja,> 10-100K) e em outras circunstâncias (consulte os benchmarks abaixo)dplyr
tem sintaxe mais acessíveldplyr
abstrai (ou irá) possíveis interações com o banco de dados- Existem algumas pequenas diferenças de funcionalidade (consulte "Exemplos / uso" abaixo)
Na minha opinião, 2. não tem muito peso porque estou bastante familiarizado com isso data.table
, apesar de entender que, para os novos usuários de ambos, será um grande fator. Eu gostaria de evitar uma discussão sobre o que é mais intuitivo, pois isso é irrelevante para minha pergunta específica feita da perspectiva de alguém já familiarizado data.table
. Também gostaria de evitar uma discussão sobre como "mais intuitivo" leva a análises mais rápidas (certamente verdade, mas, novamente, não é o que mais me interessa aqui).
Questão
O que eu quero saber é:
- Existem tarefas analíticas muito mais fáceis de codificar com um ou outro pacote para pessoas familiarizadas com os pacotes (ou seja, alguma combinação de pressionamentos de tecla exigida versus nível de esoterismo exigido, em que menos de cada uma é uma coisa boa).
- Existem tarefas analíticas executadas substancialmente (ou seja, mais de 2x) com mais eficiência em um pacote versus outro.
Uma recente pergunta do SO me fez pensar um pouco mais sobre isso, porque até aquele momento eu não pensava dplyr
em oferecer muito além do que já posso fazer data.table
. Aqui está a dplyr
solução (dados no final de Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
O que foi muito melhor do que minha tentativa de hackear uma data.table
solução. Dito isto, boas data.table
soluções também são muito boas (obrigado Jean-Robert, Arun, e observe que eu favoreci a declaração única sobre a solução estritamente mais ideal):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
A sintaxe para o último pode parecer muito esotérica, mas na verdade é bastante direta se você está acostumado data.table
(ou seja, não usa alguns dos truques mais esotéricos).
Idealmente, o que eu gostaria de ver são alguns bons exemplos, se a maneira dplyr
ou data.table
for substancialmente mais concisa ou tiver um desempenho substancialmente melhor.
Exemplos
Usodplyr
não permite operações agrupadas que retornam número arbitrário de linhas ( da pergunta de eddi , observe: isso parece que será implementado no dplyr 0.5 , também, @beginneR mostra uma possíveldo
solução alternativa usando a resposta à pergunta de @ eddi).data.table
suporta junções rolantes (obrigado @dholstius), bem como junções de sobreposiçãodata.table
otimiza internamente expressões do formulárioDT[col == value]
ouDT[col %in% values]
para velocidade por meio de indexação automática que usa pesquisa binária enquanto usa a mesma sintaxe R básica. Veja aqui para mais alguns detalhes e uma pequena referência.dplyr
oferece versões de avaliação padrão de funções (por exemploregroup
,summarize_each_
) que podem simplificar o uso programático dedplyr
(note que o uso programático dedata.table
é definitivamente possível, requer apenas uma reflexão cuidadosa, substituição / citação, etc., pelo menos que eu saiba)
- Fiz meus próprios benchmarks e achei os dois pacotes comparáveis na análise de estilo "split apply combine", exceto quando há um número muito grande de grupos (> 100K), quando o ponto
data.table
se torna substancialmente mais rápido. - @Arun correu alguns benchmarks em junções , mostrando que as
data.table
escalas são melhores do quedplyr
quando o número de grupos aumenta (atualizado com aprimoramentos recentes nos pacotes e na versão recente do R). Além disso, uma referência ao tentar obter valores exclusivos temdata.table
~ 6x mais rápido. - (Não verificado) tem
data.table
75% mais rápido em versões maiores de um grupo / aplicar / classificar, enquantodplyr
foi 40% mais rápido em versões menores ( outra questão SO dos comentários , obrigado danas). - Matt, o principal autor de
data.table
, tenha aferido operações agrupamento emdata.table
,dplyr
e pythonpandas
em até 2 bilhões de linhas (~ 100GB de RAM) . - A referência mais antiga em grupos de 80K tem
data.table
~ 8x mais rápido
Dados
Este é o primeiro exemplo que mostrei na seção de perguntas.
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane",
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob",
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L,
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L,
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager",
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager",
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L,
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id",
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA,
-16L))
fonte
dplyr
um é:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]
dplyr
edata.table
equipes estão trabalhando em benchmarks, portanto, uma resposta vai estar lá em algum ponto. # 2 (sintaxe) imO é estritamente falso, mas isso claramente se aventura no território das opiniões, por isso estou votando para fechar também.(d)plyr
tem medida 0dplyr
eplyr
com relação à sintaxe, e é basicamente a principal razão pela qual eu não gosto da sintaxe deles, é que eu tenho que aprender muitas funções extras (leia mais de 1) (com nomes que ainda não faz sentido para mim), lembre-se do que eles fazem, que argumentos eles tomam etc. Isso sempre foi uma grande desvantagem para mim da filosofia da plyr..SD
). [sério] Eu acho que essas são diferenças legítimas de design que irão agradar a pessoas diferentesRespostas:
Precisamos de cobertura, pelo menos estes aspectos para fornecer uma abrangente resposta / comparação (em nenhuma ordem particular de importância):
Speed
,Memory usage
,Syntax
eFeatures
.Minha intenção é cobrir cada um deles o mais claramente possível da perspectiva data.table.
A sintaxe data.table é consistente em sua forma -
DT[i, j, by]
. Para manteri
,j
eby
juntos é por design. Ao manter as operações relacionadas juntas, ele permite otimizar facilmente as operações de velocidade e, mais importante, o uso da memória , além de fornecer alguns recursos poderosos , mantendo a consistência na sintaxe.1. Speed
Muito poucas benchmarks (embora na maior parte em operações de agrupamento) foram adicionados à questão já mostrando data.table fica mais rápido do que dplyr como o número de grupos e / ou linhas para grupo de aumento, incluindo benchmarks por Matt no agrupamento de 10 milhões para 2 bilhões de linhas (100 GB de RAM) em 100 a 10 milhões de grupos e colunas de agrupamento variáveis, que também são comparadas
pandas
. Consulte também benchmarks atualizados , que incluemSpark
epydatatable
também.Nos benchmarks, seria ótimo cobrir também esses aspectos restantes:
Operações de agrupamento envolvendo um subconjunto de linhas - ou seja,
DT[x > val, sum(y), by = z]
operações de tipo.Compare outras operações, como atualização e junções .
Também avalie a pegada de memória para cada operação, além do tempo de execução.
2. Uso de memória
As operações que envolvem
filter()
ouslice()
no dplyr podem ser ineficientes na memória (nos quadros de dados e tabelas de dados). Veja este post .No momento, a interface data.table permite modificar / atualizar colunas por referência (observe que não precisamos atribuir novamente o resultado a uma variável).
Mas o dplyr nunca será atualizado por referência. O equivalente dplyr seria (observe que o resultado precisa ser redesignado):
Uma preocupação para isso é a transparência referencial . Atualizar um objeto data.table por referência, especialmente dentro de uma função, nem sempre é desejável. Mas esse é um recurso incrivelmente útil: veja este e este post para casos interessantes. E nós queremos mantê-lo.
Portanto, estamos trabalhando para exportar a
shallow()
função no data.table que fornecerá ao usuário as duas possibilidades . Por exemplo, se é desejável não modificar a tabela de dados de entrada em uma função, é possível:Ao não usar
shallow()
, a funcionalidade antiga é mantida:Ao criar uma cópia superficial usando
shallow()
, entendemos que você não deseja modificar o objeto original. Nós cuidamos de tudo internamente para garantir que, ao mesmo tempo, assegure-se de copiar as colunas que você modifica apenas quando for absolutamente necessário . Quando implementado, isso deve resolver completamente a questão da transparência referencial , fornecendo ao usuário as duas possibilidades.Agregue ao ingressar:
Suponha que você tenha duas tabelas de dados da seguinte maneira:
E você gostaria de obter
sum(z) * mul
para cada linhaDT2
ao ingressar em colunasx,y
. Nós podemos:1) agregar
DT1
para obtersum(z)
, 2) realizar uma junção e 3) multiplicar (ou)2) faça tudo de uma só vez (usando o
by = .EACHI
recurso):Qual a vantagem?
Não precisamos alocar memória para o resultado intermediário.
Não precisamos agrupar / hash duas vezes (um para agregação e outro para associação).
E, mais importante, a operação que queríamos executar é clara olhando
j
em (2).Confira este post para uma explicação detalhada de
by = .EACHI
. Nenhum resultado intermediário é materializado, e a junção + agregada é realizada de uma só vez.Dê uma olhada nisso , isso e isso postagens para cenários de uso real.
Em
dplyr
você teria que ingressar e agregar ou agregar primeiro e depois ingressar , nenhum dos quais são tão eficientes, em termos de memória (que por sua vez se traduz em velocidade).Atualização e junções:
Considere o código data.table mostrado abaixo:
adiciona / atualiza
DT1
a colunacol
commul
deDT2
nas linhas em queDT2
a coluna principal correspondeDT1
. Eu não acho que exista um equivalente exato dessa operação emdplyr
, ou seja, sem evitar uma*_join
operação, que teria que copiar todo oDT1
apenas para adicionar uma nova coluna a ela, o que é desnecessário.Verifique esta postagem para um cenário de uso real.
3. Sintaxe
Vamos agora olhar para a sintaxe . Hadley comentou aqui :
Acho essa observação inútil porque é muito subjetiva. O que talvez possamos tentar é contrastar a consistência na sintaxe . Compararemos a sintaxe data.table e dplyr lado a lado.
Trabalharemos com os dados fictícios mostrados abaixo:
Operações básicas de agregação / atualização.
A sintaxe data.table é compacta e o dplyr é bastante detalhado. As coisas são mais ou menos equivalentes no caso (a).
No caso (b), tivemos que usar
filter()
em dplyr enquanto resumindo . Mas durante a atualização , tivemos que mudar a lógica para dentromutate()
. No data.table, no entanto, expressamos as duas operações com a mesma lógica - operamos em linhas ondex > 2
, mas no primeiro caso, obtémsum(y)
, enquanto no segundo caso atualizamos essas linhasy
com sua soma cumulativa.É isso que queremos dizer quando dizemos que o
DT[i, j, by]
formulário é consistente .Da mesma forma, no caso (c), quando temos
if-else
condição, somos capazes de expressar a lógica "como está" tanto em data.table quanto em dplyr. No entanto, se quisermos retornar apenas as linhas em que aif
condição satisfaz e pular de outra forma, não podemos usarsummarise()
diretamente (AFAICT). Temos quefilter()
primeiro e depois resumir, porquesummarise()
sempre espera um valor único .Embora retorne o mesmo resultado, usar
filter()
aqui torna a operação real menos óbvia.Pode muito bem ser possível usar também
filter()
no primeiro caso (não me parece óbvio), mas meu argumento é que não devemos.Agregação / atualização em várias colunas
No caso (a), os códigos são mais ou menos equivalentes. data.table usa a função base familiar
lapply()
, ao passo quedplyr
apresenta,*_each()
juntamente com várias funções ,funs()
.O data.table's
:=
requer que os nomes das colunas sejam fornecidos, enquanto o dplyr os gera automaticamente.No caso (b), a sintaxe do dplyr é relativamente direta. Melhorar agregações / atualizações em várias funções está na lista de data.table.
No caso (c), o dplyr retornaria
n()
tantas vezes quantas colunas, em vez de apenas uma vez. No data.table, tudo o que precisamos fazer é retornar uma listaj
. Cada elemento da lista se tornará uma coluna no resultado. Assim, podemos usar, mais uma vez, a função básica familiarc()
para concatenar.N
a umalist
que retorna alist
.Junções
O dplyr fornece funções separadas para cada tipo de junção, em que data.table permite junções usando a mesma sintaxe
DT[i, j, by]
(e com razão). Ele também fornece umamerge.data.table()
função equivalente como alternativa.Alguns podem encontrar uma função separada para cada junção muito melhor (esquerda, direita, interna, anti, semi etc), enquanto outros podem gostar de data.table's
DT[i, j, by]
, oumerge()
que é semelhante à base R.No entanto, o dplyr join faz exatamente isso. Nada mais. Nada menos.
O data.tables pode selecionar colunas durante a junção (2) e, no dplyr, você precisará
select()
primeiro nos data.frames antes de ingressar, como mostrado acima. Caso contrário, você usaria a junção com colunas desnecessárias apenas para removê-las posteriormente e isso é ineficiente.O data.tables pode ser agregado ao ingressar (3) e também atualizar ao ingressar (4), usando o
by = .EACHI
recurso Por que materializar todo o resultado da junção para adicionar / atualizar apenas algumas colunas?data.table é capaz de rolar junções (5) - rolar para frente, LOCF , rolar para trás, NOCB , mais próximo .
data.table também possui
mult =
argumento que seleciona primeiro , último ou todos os resultados (6).data.table tem
allow.cartesian = TRUE
argumento para se proteger de junções acidentais inválidas.do()
...O resumo do dplyr é projetado especialmente para funções que retornam um único valor. Se sua função retornar valores múltiplos / desiguais, você precisará recorrer
do()
. Você precisa saber de antemão sobre todas as suas funções retornam valor..SD
O equivalente de.
No data.table, você pode lançar praticamente qualquer coisa
j
- a única coisa a lembrar é retornar uma lista para que cada elemento da lista seja convertido em uma coluna.No dplyr, não pode fazer isso. É necessário recorrer,
do()
dependendo da certeza de que sua função retornaria sempre um único valor. E é bem lento.Dê uma olhada nesta questão SO e esta . Gostaria de saber se seria possível expressar a resposta como direta usando a sintaxe do dplyr ...
4. Recursos
Eu apontei a maioria dos recursos aqui e também neste post. Além do que, além do mais:
O leitor de arquivos fread -fast está disponível há muito tempo.
fwrite - um gravador de arquivos rápido em paralelo está agora disponível. Veja este post para obter uma explicação detalhada sobre a implementação e # 1664 para acompanhar os desenvolvimentos futuros.
Indexação automática - outro recurso útil para otimizar a sintaxe básica de R, internamente.
Agrupamento ad-hoc :
dplyr
classifica automaticamente os resultados agrupando variáveis durantesummarise()
, o que nem sempre é desejável.Inúmeras vantagens nas junções data.table (para eficiência de velocidade / memória e sintaxe) mencionadas acima.
<=, <, >, >=
Junções não equi : permite junções usando outros operadores, além de todas as outras vantagens das junções data.table.As junções de intervalo sobrepostas foram implementadas recentemente em data.table. Confira esta postagem para uma visão geral com referências.
setorder()
função no data.table que permite uma reordenação realmente rápida do data.tables por referência.O dplyr fornece interface para bancos de dados usando a mesma sintaxe, que data.table não possui no momento.
data.table
fornece equivalentes mais rápidos de operações de conjunto (escrito por Jan Gorecki) -fsetdiff
,fintersect
,funion
efsetequal
com adicionalall
argumento (como em SQL).O data.table é carregado de forma limpa, sem avisos de mascaramento e possui um mecanismo descrito aqui para
[.data.frame
compatibilidade quando passado para qualquer pacote R. dplyr muda funções de basefilter
,lag
e[
que pode causar problemas; por exemplo, aqui e aqui .Finalmente:
Nos bancos de dados - não há razão para que o data.table não possa fornecer uma interface semelhante, mas isso não é uma prioridade agora. Pode ser difícil se os usuários gostarem muito desse recurso ... não tenho certeza.
No paralelismo - Tudo é difícil, até que alguém vá em frente e faça. É claro que será necessário esforço (sendo seguro para threads).
OpenMP
.fonte
:=
),dplyr
equivalente devem ser também utilizando<-
como emDF <- DF %>% mutate...
vez de apenasDF %>% mutate...
dplyr
pode ser mais fácil para usuários que costumavam fazerplyr
sintaxe, masdata.table
pode ser mais fácil para usuários que costumavam consultar linguagens como a sintaxeSQL
e a álgebra relacional por trás dela, que trata da transformação de dados tabulares. @ Arun, você deve observar que os operadores de conjunto são muito fáceis de executar, envolvendo adata.table
função e, é claro, traz uma aceleração significativa.Aqui está minha tentativa de uma resposta abrangente da perspectiva dplyr, seguindo o amplo esboço da resposta de Arun (mas um pouco reorganizada com base em diferentes prioridades).
Sintaxe
Há alguma subjetividade na sintaxe, mas eu mantenho minha afirmação de que a concisão de data.table torna mais difícil de aprender e mais difícil de ler. Isso ocorre em parte porque o dplyr está resolvendo um problema muito mais fácil!
Uma coisa realmente importante que o dplyr faz por você é que ele restringe suas opções. Afirmo que a maioria dos problemas de tabela única pode ser resolvida com apenas cinco verbos principais, filtrar, selecionar, alterar, organizar e resumir, juntamente com um advérbio "por grupo". Essa restrição é uma grande ajuda quando você está aprendendo a manipulação de dados, porque ajuda a ordenar sua opinião sobre o problema. No dplyr, cada um desses verbos é mapeado para uma única função. Cada função executa um trabalho e é fácil de entender isoladamente.
Você cria complexidade canalizando essas operações simples
%>%
. Aqui está um exemplo de uma das postagens às quais Arun vinculou :Mesmo se você nunca viu o dplyr antes (ou mesmo o R!), Ainda pode entender o que está acontecendo, porque as funções são todos verbos em inglês. A desvantagem dos verbos em inglês é que eles exigem mais digitação do que
[
, mas acho que isso pode ser amplamente mitigado por um preenchimento automático melhor.Aqui está o código data.table equivalente:
É mais difícil seguir esse código, a menos que você já esteja familiarizado com o data.table. (Eu também não conseguia descobrir como recuar o repetido
[
de uma maneira que pareça boa para os meus olhos). Pessoalmente, quando olho para o código que escrevi há 6 meses, é como olhar para um código escrito por um estranho, então passei a preferir um código direto, se bem detalhado.Dois outros fatores menores que eu acho que diminuem ligeiramente a legibilidade:
Como quase todas as operações da tabela de dados usam,
[
você precisa de um contexto adicional para descobrir o que está acontecendo. Por exemplo,x[y]
juntar duas tabelas de dados ou extrair colunas de um quadro de dados? Esse é apenas um pequeno problema, porque em códigos bem escritos os nomes das variáveis devem sugerir o que está acontecendo.Eu gosto que
group_by()
é uma operação separada no dplyr. Isso muda fundamentalmente a computação, então eu acho que deveria ser óbvio ao analisar o código, e é mais fácil identificar dogroup_by()
que oby
argumento[.data.table
.Também gosto que o cano não se limite apenas a um pacote. Você pode começar organizando seus dados com o tidyr e finalizando com um gráfico no ggvis . E você não está limitado aos pacotes que eu escrevo - qualquer um pode escrever uma função que faz parte integrante de um tubo de manipulação de dados. Na verdade, prefiro o código data.table reescrito com
%>%
:E a ideia de canalizar
%>%
não se limita apenas a quadros de dados e é facilmente generalizada para outros contextos: gráficos interativos da Web , raspagem da Web , dicas , contratos de tempo de execução , ...)Memória e desempenho
Eu os juntei porque, para mim, eles não são tão importantes. A maioria dos usuários de R trabalha com menos de 1 milhão de linhas de dados, e o dplyr é suficientemente rápido para esse tamanho de dados que você não conhece o tempo de processamento. Otimizamos o dplyr para expressividade em dados médios; fique à vontade para usar data.table para obter velocidade bruta em dados maiores.
A flexibilidade do dplyr também significa que você pode ajustar facilmente as características de desempenho usando a mesma sintaxe. Se o desempenho do dplyr com o back-end do quadro de dados não for bom o suficiente para você, você poderá usar o back-end data.table (embora com um conjunto de funcionalidades um tanto restrito). Se os dados com os quais você está trabalhando não cabem na memória, é possível usar um back-end do banco de dados.
Tudo isso dito, o desempenho do dplyr melhorará a longo prazo. Definitivamente, implementaremos algumas das grandes idéias de data.table, como ordenação por raiz e uso do mesmo índice para junções e filtros. Também estamos trabalhando na paralelização para que possamos tirar proveito de vários núcleos.
Recursos
Algumas coisas que planejamos trabalhar em 2015:
o
readr
pacote, para facilitar a retirada de arquivos do disco e da memória, análoga afread()
.Junções mais flexíveis, incluindo suporte para junções não equi.
Agrupamento mais flexível, como amostras de bootstrap, rollups e muito mais
Também estou investindo tempo na melhoria dos conectores de banco de dados de R , na capacidade de conversar com APIs da Web e em facilitar a raspagem de páginas html .
fonte
data.table
sintaxe), mas você pode usá-lo facilmente%>%
para canalizardata.table
operações se não gostar de[
estilo.%>%
não é específicodplyr
, mas vem de um pacote separado (do qual você também é co-autor), então não tenho certeza de que entendi o que você está tentando dizer na maioria dos parágrafos da sintaxe .%>%
com data.tableDT[\n\texpression\n][\texpression\n]
( gist ) que realmente funciona muito bem. Estou mantendo a resposta de Arun como a resposta, pois ele responde mais diretamente às minhas perguntas específicas, que não são muito sobre a acessibilidade da sintaxe, mas acho que é uma boa resposta para as pessoas que tentam ter uma idéia geral das diferenças / semelhanças entredplyr
edata.table
.fread()
? Não seria melhor gastar tempo melhorando o fread () ou trabalhando em outras coisas (subdesenvolvidas)?data.table
baseia-se em um abuso maciço da[]
notação. Essa é sua maior força e sua maior fraqueza.Em resposta direta ao título da pergunta ...
dplyr
definitivamente faz coisas quedata.table
não podem.O seu ponto # 3
é uma resposta direta à sua própria pergunta, mas não é elevada a um nível alto o suficiente.
dplyr
é realmente um front-end extensível para vários mecanismos de armazenamento de dados, edata.table
também uma extensão para um único.Veja
dplyr
como uma interface independente de back-end, com todos os destinos usando a mesma gramática, onde você pode estender os destinos e manipuladores à vontade.data.table
é, dodplyr
ponto de vista, um desses alvos.Você (nunca) verá (espero) um dia que
data.table
tente traduzir suas consultas para criar instruções SQL que operam com armazenamentos de dados em disco ou em rede.dplyr
possivelmente pode fazer coisasdata.table
que não farão ou não.Com base no design de trabalhar na memória,
data.table
pode ser muito mais difícil se estender para o processamento paralelo de consultas do quedplyr
.Em resposta às perguntas do corpo ...
Uso
Isso pode parecer um truque, mas a resposta real é não. As pessoas familiarizadas com as ferramentas parecem usar a mais familiar ou a mais adequada para o trabalho em questão. Com isso dito, às vezes você deseja apresentar uma legibilidade específica, às vezes um nível de desempenho, e quando você precisa de um nível alto o suficiente de ambos, você pode precisar apenas de outra ferramenta para acompanhar o que você já tem para tornar abstrações mais claras .
atuação
Novamente não.
data.table
destaca-se por ser eficiente em tudo o que faz, ondedplyr
fica o ônus de ser limitado em alguns aspectos ao armazenamento de dados subjacente e aos manipuladores registrados.Isso significa que, quando você se deparar com um problema de desempenho,
data.table
pode ter certeza de que ele está na sua função de consulta e se é realmente um gargalodata.table
, você ganhou a alegria de arquivar um relatório. Isso também é verdade quandodplyr
está sendo usadodata.table
como back-end; você pode ver algumas despesas gerais,dplyr
mas é provável que seja sua consulta.Quando
dplyr
há problemas de desempenho com back-ends, é possível contorná-los registrando uma função para avaliação híbrida ou (no caso de bancos de dados) manipulando a consulta gerada antes da execução.Veja também a resposta aceita para quando o plyr é melhor que o data.table?
fonte