Hallo. Ich bin verwirrt über das Verhalten von data.table beim Aggregieren und Gruppieren in derselben Spalte. Es scheint das Aggregat (z. B. die Summe) für die gruppierten Daten und nicht für die nicht gruppierten Daten durchzuführen. Ich sage nicht unbedingt, dass dies falsch ist - aber es unterscheidet sich von anderen Tools und ich habe mich gefragt, was die Erklärung ist oder ob ich etwas falsch mache (oder ob dies möglicherweise ein Fehler ist). Ich habe einen Vergleich mit dplyr beigefügt, der mehr wie erwartet (und eher wie SQL) funktioniert. NB: Ich habe versucht, die Probleme, den Stapelüberlauf usw. wie gewünscht zu durchsuchen, aber die Art dieses Szenarios (Gruppieren und Aggregieren derselben Spalte) ist etwas eindeutig und ich habe keine Übereinstimmungen gefunden.
#
Minimal reproducible example
Bitte vergleichen Sie die Spalte Gesamt in den beiden folgenden Beispielen. ZB gibt es drei Zeilen mit dem Wert drei, also würde ich erwarten, dass die Summe 9 ist, nicht 3.
Datentabelle
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]
Ergebnis (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()
Ergebnis (r):
SomeNumber N Total
1: 1 3 3
2: 2 3 6
3: 3 3 9
#
Output of sessionInfo()
R Version 3.5.1 (2018-07-02)
Plattform: x86_64-w64-mingw32 / x64 (64-Bit)
Läuft unter: Windows> = 8 x64 (Build 9200)
Matrix-Produkte: Standard
Gebietsschema:
[1] LC_COLLATE = English_United Kingdom.1252 LC_CTYPE = English_United Kingdom.1252 LC_MONETARY = English_United Kingdom.1252
[4] LC_NUMERIC = C LC_TIME = English_United Kingdom.1252
beigefügte Basispakete:
[1] Statistik Grafik GrDevices Utils Datasets Methoden Basis
andere angehängte Pakete:
[1] dplyr_0.7.6 data.table_1.11.8 openxlsx_4.1.0 bindrcpp_0.2.2 pivottabler_0.4.0.9000
über einen Namespace geladen (und nicht angehängt):
[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
Es unterscheidet sich von anderen Tools und ich habe mich gefragt, was die Erklärung ist oder ob ich etwas falsch mache (oder ob dies möglicherweise ein Fehler ist). Ich habe einen Vergleich mit dplyr beigefügt, der mehr wie erwartet (und eher wie SQL) funktioniert.
Innerhalb von j
von DT[, j, by]
haben die Spalten in by
eine Länge von 1. Sie können diese Berechnung jedoch wie .N*SomeNumber
:
dt[, .(.N, Total=.N*SomeNumber), by=SomeNumber]
# or, for efficiency with GForce...
dt[, .(.N), by=SomeNumber][, Total := N*SomeNumber][]
Eine Begründung finden Sie in der Frage "Warum sind die Gruppenvariablen in jeder Gruppe Länge-1?" in den FAQ unter vignette("datatable-faq")
oder https://github.com/Rdatatable/data.table/wiki/Getting-started
Vielen Dank an @ franknarf1 und @jangorecki für die Antwort und den
Nachdem Sie die FAQ-Antwort gelesen und einige weitere Tests durchgeführt haben, müssen Sie anscheinend sehr vorsichtig mit der Verwendung von Gruppierungsvariablen umgehen, da die Aggregation in verschiedenen Spalten mit identischen Daten zu unterschiedlichen Ergebnissen führen kann, je nachdem, was für die Gruppierung verwendet wurde. Ich finde das immer noch seltsam und etwas umständlich, aber vielleicht ist das nur etwas, woran ich mich gewöhnen muss.
Beispiele:
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]
Ergebnis des oben genannten: 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]
Ergebnis des oben genannten: 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]
Kein Ergebnis, kann nicht mit Fehler ausgeführt werden:
Fehler in gsum (SomeNumberA): Objekt 'SomeNumberA' nicht gefunden
Der letzte ist ein Fehler ...
Ich bin nicht sicher, ob dies eine Nuance der Gruppierungs- / Aggregationsmethode von data.table ist, aber wenn die Gruppierung und Aggregation nach einer einzelnen Variablen data.table den Gruppierungsaufruf nicht "faktorisiert".
Das heißt, jede Zahl wird nach der Aggregation als eigene Gruppe gezählt. In Ihrem Fall bleiben also nur 3 SomeNumber
Variablen zu summieren, anstatt der ursprünglichen 9.
Durch die schnelle und einfache Lösung wird sichergestellt, dass die Faktorisierung innerhalb des ersten Gruppierungsaufrufs erfolgt.
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
Hilfreichster Kommentar
Vielen Dank an @ franknarf1 und @jangorecki für die Antwort und den
Nachdem Sie die FAQ-Antwort gelesen und einige weitere Tests durchgeführt haben, müssen Sie anscheinend sehr vorsichtig mit der Verwendung von Gruppierungsvariablen umgehen, da die Aggregation in verschiedenen Spalten mit identischen Daten zu unterschiedlichen Ergebnissen führen kann, je nachdem, was für die Gruppierung verwendet wurde. Ich finde das immer noch seltsam und etwas umständlich, aber vielleicht ist das nur etwas, woran ich mich gewöhnen muss.
Beispiele:
Ergebnis des oben genannten: TotalA = 1
Ergebnis des oben genannten: TotalB = 3
Kein Ergebnis, kann nicht mit Fehler ausgeführt werden:
Fehler in gsum (SomeNumberA): Objekt 'SomeNumberA' nicht gefunden