35

私は 1 日あたりの出会いのために enc.per.day という data.table を持っています。サービスの日付とその日に受診した患者数を指定する 2403 行があります。あらゆるタイプの平日に受診する患者数の中央値を確認したかったのです。

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

その行はエラーを出します

(enc.per.day, , list(patient.encounters = median(n)) のエラー[.data.table: j の列は各グループの一貫した型に評価されません: グループ 4 の結果は列 1 の型 'integer' を持っていますが、期待しています「ダブル」と入力

以下はすべてうまくいきます

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))]

何が起こっている?コードが機能しない理由を理解するのに長い時間がかかりました。

ちなみに、基礎となるベクトル enc.per.day$n は整数です

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

「整数」を返します。さらに、data.table のどこにも NA はありません。

4

1 に答える 1

50

TL;DRmedianラップas.double()

median()---渡された整数ベクトルのみの場合でも---整数値を返す場合とdoubleを返す場合があるため、 data.tableを「トリップアップ」します。median()

## 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"

最小限の例でエラーメッセージを再現します。

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は、処理される最初のグループの値を検査した後、OK、これらの結果は「整数」タイプになると結論付けたため、文句を言います。しかし、すぐに(または、グループ4の場合)、タイプ「double」の値が渡されます。これは、「整数」の結果ベクトルに適合しません。


data.tableは、代わりにグループ単位の計算が終了するまで結果を蓄積し、必要に応じて型変換を実行できますが、これにはパフォーマンスを低下させる大量のオーバーヘッドが必要になります。代わりに、何が起こったかを報告し、問題を修正することができます。最初のグループが実行され、結果のタイプがわかった後、グループの数だけそのタイプの結果ベクトルが割り当てられ、データが入力されます。後でいくつかのグループが複数のアイテムを返すことがわかった場合、必要に応じてその結果ベクトルを拡大(つまり再割り当て)します。ただし、ほとんどの場合data.table、結果の最終的なサイズの最初の推測は最初から正しく(たとえば、グループごとに1行の結果)、したがって高速です。

この場合、as.double(median(X))代わりにを使用median(X)すると適切な修正が提供されます。

(ちなみに、使用しているバージョンround()は、入力するとわかるように、常に「double」タイプの値を返すため、機能しましたtypeof(round(median(1:2))); typeof(round(median(1:3)))。)

于 2012-08-25T21:43:24.033 に答える