Data.table: Totais errados ao agregar e agrupar pela mesma coluna?

Criado em 10 out. 2018  ·  4Comentários  ·  Fonte: Rdatatable/data.table

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

bug question

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:

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

Todos 4 comentários

é 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
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

mattdowle picture mattdowle  ·  3Comentários

jangorecki picture jangorecki  ·  3Comentários

alex46015 picture alex46015  ·  3Comentários

franknarf1 picture franknarf1  ·  3Comentários

pannnda picture pannnda  ·  3Comentários