2014-08-29 20 views
17

Hãy xem xét vector có tên sau đây x.Tính toán cumsum() trong khi bỏ qua các giá trị NA

(x <- setNames(c(1, 2, 0, NA, 4, NA, NA, 6), letters[1:8])) 
# a b c d e f g h 
# 1 2 0 NA 4 NA NA 6 

tôi muốn để tính toán số tiền tích lũy của x trong khi bỏ qua các NA giá trị. Vì không có đối số na.rm cho cumsum(), điều này hơi phức tạp một chút.

Tôi có thể thực hiện theo cách này.

y <- setNames(numeric(length(x)), names(x)) 
z <- cumsum(na.omit(x)) 
y[names(y) %in% names(z)] <- z 
y[!names(y) %in% names(z)] <- x[is.na(x)] 
y 
# a b c d e f g h 
# 1 3 3 NA 7 NA NA 13 

Nhưng điều này có vẻ quá mức và tạo nhiều bài tập/bản sao mới. Tôi chắc chắn có một cách tốt hơn.

Có phương pháp nào tốt hơn để trả lại tổng tích lũy trong khi bỏ qua hiệu quả các giá trịNA?

Trả lời

12

Bạn có muốn một cái gì đó như thế này:

x2 <- x 
x2[!is.na(x)] <- cumsum(x2[!is.na(x)]) 

x2 

[sửa] Ngoài ra, theo đề nghị của một bình luận ở trên, bạn có thể thay đổi NA với tỉ số 0 của -

miss <- is.na(x) 
x[miss] <- 0 
cs <- cumsum(x) 
cs[miss] <- NA 
# cs is the requested cumsum 
+0

một lớp lót làm cùng một điều: '" [<- "(x,! Is.na (x), cumsum (na.omit (x)))' – lebatsnok

+1

Không phải là phiên bản dễ đọc hơn của cùng một điều 'x [! is.na (x)] <- cumsum (na.omit (x))'? –

+2

Nó dễ đọc hơn nhưng không giống nhau. '" [<- "(x, bla ...' làm những gì OP yêu cầu * mà không thay đổi x *, phiên bản của bạn không gán sub trên x và trả về 'cumsum (na.omit (x))'. cùng một điều - Một phiên bản dễ đọc hơn của một lớp lót, làm điều tương tự, sẽ là: 'thay thế (x,! is.na (x), cumsum (na.omit (x)))' – lebatsnok

21

Bạn có thể làm điều này trong một dòng với:

cumsum(ifelse(is.na(x), 0, x)) + x*0 
# a b c d e f g h 
# 1 3 3 NA 7 NA NA 13 
6

Đây là hàm tôi đã đưa ra từ câu trả lời cho câu hỏi này. Nghĩ rằng tôi sẽ chia sẻ nó, vì nó có vẻ hoạt động tốt cho đến nay. Nó tính toán số tích lũy FUNC của x khi bỏ qua NA. FUNC có thể là bất kỳ một trong số sum(), prod(), min() hoặc max()x là một vectơ số.

cumSkipNA <- function(x, FUNC) 
{ 
    d <- deparse(substitute(FUNC)) 
    funs <- c("max", "min", "prod", "sum") 
    stopifnot(is.vector(x), is.numeric(x), d %in% funs) 
    FUNC <- match.fun(paste0("cum", d)) 
    x[!is.na(x)] <- FUNC(x[!is.na(x)]) 
    x 
} 

set.seed(1) 
x <- sample(15, 10, TRUE) 
x[c(2,7,5)] <- NA 
x 
# [1] 4 NA 9 14 NA 14 NA 10 10 1 
cumSkipNA(x, sum) 
# [1] 4 NA 13 27 NA 41 NA 51 61 62 
cumSkipNA(x, prod) 
# [1]  4  NA  36 504  NA 7056  NA 
# [8] 70560 705600 705600 
cumSkipNA(x, min) 
# [1] 4 NA 4 4 NA 4 NA 4 4 1 
cumSkipNA(x, max) 
# [1] 4 NA 9 14 NA 14 NA 14 14 14 

Chắc chắn không có gì mới, nhưng có thể hữu ích cho ai đó.

+1

rất hữu ích để có một chức năng sử dụng chung như thế này - tuyệt vời – jalapic

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