Olá. Estou confuso com o comportamento de data.table ao agregar e agrupar na mesma coluna. Parece realizar a agregação (por exemplo, soma) nos dados agrupados, em vez de nos dados desagrupados. Não estou necessariamente dizendo que isso está errado - mas é diferente de outras ferramentas e eu queria saber qual é a explicação ou se estou fazendo algo errado (ou se possivelmente isso é um bug). Incluí uma comparação com dplyr, que tem um desempenho mais parecido com o que eu esperava (e mais parecido com SQL). NB: Eu tentei pesquisar os problemas, stackoverflow, etc, conforme solicitado, mas a natureza deste cenário (agrupar e agregar a mesma coluna) é um pouco única e não encontrei nenhuma correspondência.
#
Minimal reproducible example
Compare a coluna Total nos dois exemplos abaixo. Por exemplo, há três linhas com o valor três, então eu esperaria que o Total fosse 9, não 3.
Tabela de dados
library(data.table)
df <- data.frame(SomeNumber=c(1,2,3,1,2,3,1,2,3))
dt <- data.table(df)
r <- dt[, .(.N, Total=sum(SomeNumber)), by=SomeNumber]
Resultado (r):
SomeNumber N Total
1: 1 3 1
2: 2 3 2
3: 3 3 3
dplyr
library(dplyr)
df <- data.frame(SomeNumber=c(1,2,3,1,2,3,1,2,3))
r <- df %>% group_by(SomeNumber) %>%
summarise(N=n(), Total=sum(SomeNumber)) %>%
ungroup()
Resultado (r):
SomeNumber N Total
1: 1 3 3
2: 2 3 6
3: 3 3 9
#
Output of sessionInfo()
R versão 3.5.1 (02/07/2018)
Plataforma: x86_64-w64-mingw32 / x64 (64 bits)
Executando em: Windows> = 8 x64 (compilação 9200)
Produtos matriciais: padrão
localidade:
[1] LC_COLLATE = Inglês_Reino Unido.1252 LC_CTYPE = Inglês_Reino Unido.1252 LC_MONETARY = Inglês_Reino Unido.1252
[4] LC_NUMERIC = C LC_TIME = Inglês_Reino Unido.1252
pacotes básicos anexados:
[1] gráficos de estatísticas base de métodos de conjuntos de dados de utilitários de grDevices
outros pacotes anexados:
[1] dplyr_0.7.6 data.table_1.11.8 openxlsx_4.1.0 bindrcpp_0.2.2 pivottabler_0.4.0.9000
carregado por meio de um namespace (e não anexado):
[1] Rcpp_0.12.19 rstudioapi_0.8 bindr_0.1.1 magrittr_1.5 tidyselect_0.2.4 R6_2.3.0 rlang_0.2.2 fansi_0.3.0 tools_3.5.1
[10] utf8_1.1.4 cli_1.0.1 htmltools_0.3.6 yaml_2.2.0 assertthat_0.2.0 digest_0.6.17 tibble_1.4.2 crayon_1.3.4 zip_1.0.0
[19] purrr_0.2.5 htmlwidgets_1.3 glue_1.3.0 compiler_3.5.1 pillar_1.3.0 jsonlite_1.5 pkgconfig_2.0.2
é diferente de outras ferramentas e gostaria de saber qual é a explicação ou se estou fazendo algo errado (ou se possivelmente isso é um bug). Incluí uma comparação com dplyr, que tem um desempenho mais parecido com o que eu esperava (e mais parecido com SQL)
Dentro de j
de DT[, j, by]
, as colunas em by
têm um comprimento de 1. Você pode fazer esse cálculo como .N*SomeNumber
, embora:
dt[, .(.N, Total=.N*SomeNumber), by=SomeNumber]
# or, for efficiency with GForce...
dt[, .(.N), by=SomeNumber][, Total := N*SomeNumber][]
Para uma justificativa, consulte a pergunta "Dentro de cada grupo, por que as variáveis de grupo têm comprimento-1?" dentro do FAQ em vignette("datatable-faq")
ou https://github.com/Rdatatable/data.table/wiki/Getting-started
Obrigado @ franknarf1 e @jangorecki pela resposta e indicação para o FAQ.
Depois de ler a resposta do FAQ e fazer um pouco mais de testes, parece que você precisa ter muito cuidado ao usar variáveis de agrupamento, uma vez que agregar em colunas diferentes com dados idênticos pode resultar em resultados diferentes, dependendo do que foi usado para agrupar. Eu ainda acho isso estranho e um pouco estranho, mas talvez seja apenas algo a que eu preciso me acostumar.
Exemplos:
library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalA=sum(SomeNumberA)), by=SomeNumberA]
Resultado do acima: TotalA = 1
library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalB=sum(SomeNumberB)), by=SomeNumberA]
Resultado do acima: TotalB = 3
library(data.table)
df <- data.frame(SomeNumberA=c(1,1,1),SomeNumberB=c(1,1,1))
dt <- data.table(df)
r <- dt[, .(.N, TotalA=sum(SomeNumberA), TotalB=sum(SomeNumberB)), by=SomeNumberA]
Sem resultado, falha na execução com erro:
Erro na goma (SomeNumberA): objeto 'SomeNumberA' não encontrado
O último é um bug ...
Não tenho certeza se isso é uma nuance do método de agrupamento / agregação de data.table, mas ao agrupar e agregar por uma única variável data.table não 'fatoriza' a chamada de agrupamento.
ou seja, ele conta cada número como seu próprio grupo após a agregação, então, no seu caso, você fica com apenas 3 SomeNumber
variáveis para somar, em vez das 9 originais.
A correção rápida e fácil é garantir que a fatoração ocorra na chamada de agrupamento inicial.
library(data.table)
df <- data.frame(SomeNumber=c(1, 2, 3, 1, 2, 3, 1, 2, 3))
dt <- data.table(df)
r <- dt[, .(.N, Total = sum(SomeNumber)), by = as.factor(SomeNumber)]
as.factor N Total
1: 1 3 3
2: 2 3 6
3: 3 3 9
Comentários muito úteis
Obrigado @ franknarf1 e @jangorecki pela resposta e indicação para o FAQ.
Depois de ler a resposta do FAQ e fazer um pouco mais de testes, parece que você precisa ter muito cuidado ao usar variáveis de agrupamento, uma vez que agregar em colunas diferentes com dados idênticos pode resultar em resultados diferentes, dependendo do que foi usado para agrupar. Eu ainda acho isso estranho e um pouco estranho, mas talvez seja apenas algo a que eu preciso me acostumar.
Exemplos:
Resultado do acima: TotalA = 1
Resultado do acima: TotalB = 3
Sem resultado, falha na execução com erro:
Erro na goma (SomeNumberA): objeto 'SomeNumberA' não encontrado