在忽略NA值的同时计算cumsum()

Ric*_*ven 30 r

考虑以下命名向量x.

( 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 
Run Code Online (Sandbox Code Playgroud)

我想计算x忽略NA值的累计和.许多R函数都有一个参数na.rm,可以NA在计算之前删除元素. cumsum()不是其中之一,这使得这个操作有点棘手.

我可以这样做.

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 
Run Code Online (Sandbox Code Playgroud)

但这似乎过多了,并且制作了许多新的作业/副本.我相信有更好的方法.

在有效忽略 价值的同时,有哪些更好的方法可以返回累积金额NA

jos*_*ber 31

您可以在一行中执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)

或者,类似地:

library(dplyr)
cumsum(coalesce(x, 0)) + x*0
#  a  b  c  d  e  f  g  h 
#  1  3  3 NA  7 NA NA 13 
Run Code Online (Sandbox Code Playgroud)

  • @Denis 如果“x”中的值缺失,则“x*0”取值“NA”,否则取值 0。因此,只要原始值丢失,添加“x*0”基本上就会替换为“NA”。 (3认同)
  • `x*0` 在这里做什么? (2认同)

leb*_*nok 16

你想要这样的东西:

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

x2
Run Code Online (Sandbox Code Playgroud)

[编辑]或者,正如上面的评论所建议的那样,你可以将NA改为0 -

miss <- is.na(x)
x[miss] <- 0
cs <- cumsum(x)
cs[miss] <- NA
# cs is the requested cumsum
Run Code Online (Sandbox Code Playgroud)

  • 它更具可读性,但它不是一回事.`"[< - "(x,bla ......`执行OP问*而不改变x*,你的版本在x上进行子集赋值并返回`cumsum(na.omit(x))`.所以它到目前为止还没有同样的事情 - 一个更加可读的单行程版本,做同样的事情,就是这样:`replace(x,!is.na(x),cumsum(na.omit(x)))` (2认同)

Ric*_*ven 10

这是我从这个问题的答案中得出的一个函数.以为我会分享它,因为它似乎到目前为止运作良好.它计算累积FUNCx而忽略NA. FUNC可以是任何一个sum(),prod(),min(),或max(),并且x是一个数字向量.

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 
Run Code Online (Sandbox Code Playgroud)

绝对没什么新鲜的,但也许对某人有用.


DJV*_*DJV 10

这是一个老问题,但tidyr提供了一个新的解决方案.基于NA零替换的想法.

require(tidyr)

cumsum(replace_na(x, 0))

 a  b  c  d  e  f  g  h 
 1  3  3  3  7  7  7 13 
Run Code Online (Sandbox Code Playgroud)

  • 这包括平均值计算中的零,但我认为该帖子说他想在计算中忽略这些值。两件事都是不同的。 (6认同)