cumsum along row of data.frame with NA in R

主宰稳场 提交于 2019-12-20 03:11:30

问题


The hypothetical case is that there exist NA in a data.frame

> a <- c(1:5, NA, 7:10)
> b <- 1:10
> c <- 1:10
> 
> data <- data.frame(a,b,c)
> data
    a  b  c
1   1  1  1
2   2  2  2
3   3  3  3
4   4  4  4
5   5  5  5
6  NA  6  6
7   7  7  7
8   8  8  8
9   9  9  9
10 10 10 10
> data <- data.frame(a,b,c)
> data.frame(t(apply(data,1,cumsum)))
    a  b  c
1   1  2  3
2   2  4  6
3   3  6  9
4   4  8 12
5   5 10 15
6  NA NA NA
7   7 14 21
8   8 16 24
9   9 18 27
10 10 20 30

My desired result is

    a  b  c
1   1  2  3
2   2  4  6
3   3  6  9
4   4  8 12
5   5 10 15
6   0  6 12
7   7 14 21
8   8 16 24
9   9 18 27
10 10 20 30

or

    a  b  c
1   1  2  3
2   2  4  6
3   3  6  9
4   4  8 12
5   5 10 15
6   NA  6 12
7   7 14 21
8   8 16 24
9   9 18 27
10 10 20 30

I am not sure apply(..., cumsum) is a good option, you may provide alternative method.


回答1:


Given your desired result (where you don't mind NA becoming 0), I guess the easiest thing is to first remove the NA values using is.na and then carry on as before.

data[ is.na(data) ] <- 0
data.frame(t(apply(data,1,cumsum)))



回答2:


Simon's is definitely the simplest. I was surprised to learn a few things from this exercise: 1. cumsum doesn't have a na.rm argument 2. sum(NA, na.rm=TRUE) equals 0

Here is the code that brought me to the same solution:

cumsum.alt <- function(x){
    res <- NaN*seq(x)
    for(i in seq(x)){
        res[i] <- sum(x[1:i], na.rm=TRUE)
    }
    res
}

t(apply(data, 1, cumsum.alt))

To return the NA´s, a slight modification can be used:

cumsum.alt <- function(x){
    res <- NaN*seq(x)
    for(i in seq(x)){
        if(sum(is.na(x[1])) == i){
            res[i] <- NaN
        } else {
            res[i] <- sum(x[1:i], na.rm=TRUE)
        }
    }
    res
}

t(apply(data, 1, cumsum.alt))


来源:https://stackoverflow.com/questions/23559442/cumsum-along-row-of-data-frame-with-na-in-r

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!