2012-08-25 11 views
26

Ich habe eine data.table namens enc.per.day für Begegnungen pro Tag. Es hat 2403 Zeilen, in denen ein Datum des Dienstes angegeben ist und die Anzahl der an diesem Tag gesehenen Patienten. Ich wollte die mediane Anzahl der Patienten an jedem Wochentag sehen.Warum steigt die mittlere Datenrate der Data.table (Integer gegenüber Double)?

enc.per.day[,list(patient.encounters=median(n)),by=list(weekdays(DOS))] 

Diese Linie gibt einen Fehler

Fehler in [.data.table (enc.per.day, Liste (patient.encounters = Median (n)),: Spalten von j auswerten nicht konsequentem Typen für jede Gruppe: Ergebnis für die Gruppe hat 4 Spalte 1 Typ ‚ganze Zahl‘, aber erwartete Typ ‚doppelte‘

Die folgende Alle Arbeiten gut

tapply(enc.per.day$n,weekdays(enc.per.day$DOS),median) 
enc.per.day[,list(patient.encounters=round(median(n))),by=list(weekdays(DOS))] 
enc.per.day[,list(patient.encounters=median(n)+0),by=list(weekdays(DOS))] 

Was ist los? Es hat lange gedauert, bis ich herausgefunden habe, warum mein Code nicht funktioniert.

durch die Art der zugrunde liegenden Vektor enc.per.day $ n eine ganze Zahl

storage.mode(enc.per.day$n) 

returns "integer". Außerdem befinden sich in der data.table keine NAs.

Antwort

37

TL; DR wickeln median mit as.double()

median() 'stellt up' data.table weil --- auch wenn nur ganzzahlige Vektoren vergangen --- median() manchmal einen ganzzahligen Wert zurückgibt, und gibt manchmal einen Doppel .

## median of 1:3 is 2, of type "integer" 
typeof(median(1:3)) 
# [1] "integer" 

## median of 1:2 is 1.5, of type "double" 
typeof(median(1:2)) 
# [1] "double" 

Reproducing Ihre Fehlermeldung mit einem minimalen Beispiel:

library(data.table) 
dt <- data.table(patients = c(1:3, 1:2), 
       weekdays = c("Mon", "Mon", "Mon", "Tue", "Tue")) 

dt[,median(patients), by=weekdays] 
# Error in `[.data.table`(dt, , median(patients), by = weekdays) : 
# columns of j don't evaluate to consistent types for each group: 
# result for group 2 has column 1 type 'double' but expecting type 'integer' 

data.table beschwert sich, weil nach dem Wert der ersten Gruppe Inspektion verarbeitet werden, es kam zu dem Schluss, dass, OK, Diese Ergebnisse werden vom Typ "Integer" sein. Aber dann wird sofort (oder in Ihrem Fall in Gruppe 4) ein Wert vom Typ "double" übergeben, der nicht in den Ergebnisvektor "integer" passt.


data.table statt Ergebnisse bis zum Ende der gruppenweisen Berechnungen ansammeln könnte, und dann Typkonvertierungen durchführen, falls erforderlich, aber das würde eine Reihe von zusätzlichen Leistungsabbauoverhead erfordern; Stattdessen wird nur berichtet, was passiert ist, und Sie können das Problem beheben. Nachdem die erste Gruppe ausgeführt wurde und der Typ des Ergebnisses bekannt ist, weist sie einen Ergebnisvektor dieses Typs zu, solange die Anzahl der Gruppen vorhanden ist, und füllt ihn dann auf. Wenn es später herausfindet, dass einige Gruppen mehr als einen Gegenstand zurückgeben, wird er diesen Ergebnisvektor nach Bedarf wachsen lassen (d. H. Neu zuordnen). In den meisten Fällen ist data.table die erste Schätzung für die endgültige Größe des Ergebnisses gleich beim ersten Mal (z. B. 1 Zeilenergebnis pro Gruppe) und daher schnell.

In diesem Fall mit as.double(median(X)) statt median(X) stellt eine geeignete Lösung.

(By the way, Ihre Version mit round() gearbeitet, weil es immer Werte vom Typ "double" zurückgibt, wie Sie durch Eingabe von typeof(round(median(1:2))); typeof(round(median(1:3))) sehen können.)

+1

@Matthew Dowle - Vielen Dank für diese Informationen darüber, wie das Hinzufügen * * data.table ** initialisiert und reserviert Speicherplatz für den Ergebnisvektor. –

+0

Ist es möglich, einen Median des gleichen Typs wie den Wert zu haben? Selbst wenn ich also Werte wie = 1,1,1,2,2,2,2 hätte, sollte es nicht zu einem Median = 1,5 führen, stattdessen sollte der Median = 2 sein. – lony

+0

Als Beispiel für den obigen Vorschlag, tun Sie dies DT [, c (as.double (lapply (. SD, Median)),. N), durch = x,. SDcols = c ("x", "y “, "Z")] anstelle von DT [, C (lapply (.SD, Median), .N), by = x, .SDcols = c ("x", "y", "z")] –

Verwandte Themen