2012-08-25 27 views
26

Tôi có một data.table gọi là enc.per.day cho cuộc gặp gỡ mỗi ngày. Nó có 2403 hàng trong đó một ngày của dịch vụ được xác định và số lượng bệnh nhân nhìn thấy vào ngày đó. Tôi muốn thấy số lượng bệnh nhân trung bình được thấy trên bất kỳ loại ngày trong tuần nào.Tại sao trung bình lại tăng lên dữ liệu. (Số nguyên so với gấp đôi)?

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

dòng đó đưa ra một lỗi

Lỗi trong [.data.table (enc.per.day,, danh sách (patient.encounters = trung bình (n)),: cột j không đánh giá với các loại phù hợp cho từng nhóm: kết quả cho nhóm 4 có cột 1 loại 'nguyên' nhưng mong gõ 'đúp'

sau đây tất cả công việc cũng

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

Điều gì đang xảy ra? Tôi mất một thời gian dài để tìm ra lý do mã của tôi không hoạt động.

Bằng cách này các cơ vector enc.per.day $ n là một số nguyên

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

Thu nhập "số nguyên". Hơn nữa, không có NA bất cứ nơi nào trong data.table.

Trả lời

37

TL; DR quấn median với as.double()

median() 'chuyến đi lên' data.table vì --- ngay cả khi chỉ thông qua vectơ số nguyên --- median() đôi khi trả về một giá trị số nguyên, và đôi khi trả về một đôi .

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

Tái tạo thông báo lỗi của bạn với một ví dụ nhỏ:

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 phàn nàn bởi vì, sau khi kiểm tra giá trị của nhóm đầu tiên được xử lý, nó đã kết luận rằng, OK, những kết quả này sẽ có loại "số nguyên". Nhưng sau đó ngay lập tức (hoặc trong trường hợp của bạn trong nhóm 4), nó được thông qua một giá trị của loại "gấp đôi", mà sẽ không phù hợp trong vector kết quả "số nguyên" của nó.


data.table thay vì có thể tích lũy kết quả cho đến khi kết thúc tính toán nhóm khôn ngoan, và sau đó thực hiện chuyển đổi loại hình nếu cần thiết, nhưng điều đó sẽ đòi hỏi một loạt các thêm overhead hiệu suất phân hủy; thay vào đó, nó chỉ báo cáo những gì đã xảy ra và cho phép bạn khắc phục sự cố. Sau khi nhóm đầu tiên đã chạy, và nó biết loại kết quả, nó phân bổ một vector kết quả của loại đó miễn là số lượng nhóm, và sau đó điền nó. Nếu sau này thấy rằng một số nhóm trả về nhiều hơn 1 mục, nó sẽ tăng lên (tức là, phân bổ lại) kết quả là vector khi cần thiết. Tuy nhiên, trong hầu hết các trường hợp, dự đoán đầu tiên của data.table cho kết quả cuối cùng của kết quả là đúng thời gian đầu tiên (ví dụ: 1 kết quả hàng trên mỗi nhóm) và do đó nhanh.

Trong trường hợp này, sử dụng as.double(median(X)) thay vì median(X) cung cấp bản sửa lỗi phù hợp.

(Bằng cách này, phiên bản sử dụng round() làm việc vì nó luôn luôn trả về giá trị của loại "kép", như bạn có thể nhìn thấy bằng cách gõ typeof(round(median(1:2))); typeof(round(median(1:3))).)

+1

@Matthew Dowle - Cảm ơn bạn thêm những chi tiết về cách * * data.table ** khởi tạo và phân bổ không gian cho vectơ kết quả. –

+0

Có thể hava một trung vị cùng loại với giá trị không? Vì vậy, ngay cả khi tôi sẽ có các giá trị như = 1,1,1,2,2,2,2 nó không nên dẫn đến trung bình = 1,5 thay vì nó sẽ hiển thị trung bình = 2. – lony

+0

Làm ví dụ cho đề xuất ở trên, hãy làm điều này DT [, c (as.double (lapply (.SD, median)), .N), bởi = x, .SDcols = c ("x", "y "," z ")] thay vì DT [, c (lapply (.SD, trung bình), .N), theo = x, .SDcols = c (" x "," y "," z ")] –