2014-10-14 16 views
8

Tôi đã thực hiện hàm tổng tùy chỉnh bỏ qua NA s trừ khi tất cả là NA. Khi tôi sử dụng nó trong dplyr nó trả về kết quả lẻ và tôi không biết tại sao.Hàm tổng tùy chỉnh trong dplyr trả về kết quả không phù hợp

require(dplyr) 

dta <- data.frame(year=2007:2013, rrconf=c(79, NaN ,474,2792,1686,3313,3456), enrolled=c(NaN,NaN,458,1222,1155,1906,2184)) 

sum0 <- function(x, ...){ 
    # remove NAs unless all are NA 
    if(is.na(mean(x, na.rm=TRUE))) return(NA) 
    else(sum(x, ..., na.rm=TRUE)) 
} 

dta %>% 
    group_by(year) %>% 
    summarize(rrconf=sum0(rrconf), enrolled=sum0(enrolled)) 

mang lại cho tôi

Source: local data frame [7 x 3] 

    year rrconf enrolled 
1 2007  79  NA 
2 2008  NA  NA 
3 2009 474  TRUE 
4 2010 2792  TRUE 
5 2011 1686  TRUE 
6 2012 3313  TRUE 
7 2013 3456  TRUE 

Trong trường hợp này nó chỉ được tổng hợp qua một giá trị, nhưng trong ứng dụng lớn hơn của tôi trong mùa hè sức hơn nhiều giá trị. Bao bọc chức năng sum0 của chúng tôi trong as.integer() dường như khắc phục được nó, nhưng tôi không thể cho bạn biết lý do.

Đây có phải là cách chính xác để khắc phục sự cố này không? Có điều gì rõ ràng tôi đang thiếu?

> sessionInfo() 
R version 3.1.0 (2014-04-10) 
Platform: i386-w64-mingw32/i386 (32-bit) 

locale: 
[1] LC_COLLATE=English_United Kingdom.1252 LC_CTYPE=English_United Kingdom.1252 
[3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C       
[5] LC_TIME=English_United Kingdom.1252  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] dplyr_0.2 

loaded via a namespace (and not attached): 
[1] assertthat_0.1 magrittr_1.0.1 parallel_3.1.0 Rcpp_0.11.2 tools_3.1.0 
+0

Tôi không chắc chắn nếu điều này là cách tốt nhất để viết các chức năng nhưng dòng đó có nghĩa là để kiểm tra xem tất cả các giá trị là 'NA'. vì vậy 'sum0 (c (NA, 3, NA))' trả về 3, nhưng 'sum0 (c (NA, NA, NA))' trả về 'NA'. – Tom

+2

'tổng (x, na.rm = ifelse (tất cả (is.na (x)), FALSE, TRUE))' hoạt động? – rawr

+0

Có hành vi hơi khác giữa 'mean' và' sum' khi sử dụng 'na.rm = T'. Nếu tất cả là 'NA',' mean' trả về 'NaN', trong khi' sum' trả về 0. – Tom

Trả lời

10

Vấn đề có vẻ là với dplyr xác định loại cột trong tham chiếu đến kết quả trả về đầu tiên. Nếu bạn buộc giá trị NA, mà là theo mặc định một giá trị logic, là một NA_real_ hay NA_integer_, sau đó bạn sẽ được sắp xếp:

##Just to show what NA normally does first: 
class(NA) 
#[1] "logical" 

sum0 <- function(x, ...){ 
    # remove NAs unless all are NA 
    if(is.na(mean(x, na.rm=TRUE))) return(NA_real_) 
    else(sum(x, ..., na.rm=TRUE)) 
} 

dta %>% 
    group_by(year) %>% 
    summarize(rrconf=sum0(rrconf), enrolled=sum0(enrolled)) 

#Source: local data frame [7 x 3] 
# 
# year rrconf enrolled 
#1 2007  79  NA 
#2 2008  NA  NA 
#3 2009 474  458 
#4 2010 2792  1222 
#5 2011 1686  1155 
#6 2012 3313  1906 
#7 2013 3456  2184 
+0

Cảm ơn bạn @thelatemail có ý nghĩa. Vì vậy, các hàm bình thường trả về 'NA' làm như vậy trong lớp' đúng ''? Đó có phải là lý do tại sao sự cố này chỉ xảy ra với chức năng tùy chỉnh của tôi không? Ví dụ, tôi lưu ý rằng 'class (sum (NA))' là 'số nguyên' không phải là' logical'. – Tom

+1

@Tom - vâng, nó phải làm với thứ bậc của các loại đối tượng R khác nhau. Đó là một chút khó hiểu nhưng có lẽ câu hỏi này sẽ giúp: http://stackoverflow.com/questions/21763355/rbind-data-frame-conversion-type-hierarchy-r Tôi nghĩ rằng điều này có thể là 'dplyr' cụ thể mặc dù là một cái gì đó như' class (c (NA, 1)) 'được xử lý một cách thích hợp trong cơ sở R. – thelatemail

+2

Vì lý do hiệu năng, dplyr giả định rằng các kết quả biến đổi là" kiểu ổn định "- tức là loại phần tử đầu tiên là kiểu của tất cả các phần tử tiếp theo. Một ngày nào đó chúng ta có thể thư giãn hạn chế này, nhưng cho đến lúc đó, chỉ cần đảm bảo hàm của bạn trả về kết quả của một kiểu nhất quán. – hadley

Các vấn đề liên quan