如果所有值均为NA,则计算总和或返回NA的有效方法

Ant*_*nti 3 r sum na

在模拟过程中,我创建了多个具有1,000,000个变量的数据集。但是,这些变量的某些值是NA,在某些情况下甚至所有值都是NA。现在,我想计算变量的所有值的总和,但要获取NA所有值是否为NA

common sum(x, na.rm=T)或or 的问题sum(na.omit(x))是,如果所有值均为,则返回0 NA。因此,我编写了自己的函数,该函数NA以预期的方式处理:

sumna <- function(x) {
  sumna <- NULL
  return(ifelse(all(is.na(x)), NA, sum(na.omit(x))))
}
Run Code Online (Sandbox Code Playgroud)

但是,该实现相当慢。

因此,我正在寻找一个实现或预先实现的函数,该函数求和向量的值,如果所有值均为,则省略NA并返回。NANA

提前谢谢了!

akr*_*run 7


sum_hablar作为OP希望有相同的行为。因此,无需重新发明轮子

library(hablar)
sum_(c(1:10, NA))
#[1] 55
sum_(c(NA, NA, NA))
#[1] NA
Run Code Online (Sandbox Code Playgroud)

它可以用于tidyversedata.table

library(dplyr)
df1 %>%
    summarise_all(sum_)
Run Code Online (Sandbox Code Playgroud)

但是,如果我们需要更改OP的自定义功能,而不是ifelse,一个更好的选择是if/else

sumna <- function(x) {
       if(all(is.na(x))) NA else sum(x, na.rm = TRUE)
   }
Run Code Online (Sandbox Code Playgroud)

另外,我们可以使用向量化 colSums

v1 <- colSums(df1, na.rm = TRUE)
v1[colSums(is.na(df1)) == nrow(df1)] <- NA
Run Code Online (Sandbox Code Playgroud)

由于数据集非常庞大,我们还可以利用高效 data.table

library(data.table)
setDT(df1)[, lapply(.SD, sumna)]
Run Code Online (Sandbox Code Playgroud)

或使用 tidyverse

library(tidyverse)
df1 %>%
     summarise_all(sumna)
Run Code Online (Sandbox Code Playgroud)

  • sum_慢吗?x = rnorm(1000000); 您的`sumna()`的microbenchmark(sumna(x),sum_(x))`吗? (2认同)

GKi*_*GKi 6

您可以删除所有 NA 并测试长度是否大于 0。

sumna_a <- function(x) {
    x <- na.omit(x)
    if(length(x)) return(sum(x))
    NA
}

#or
sumna_b <- function(x) {
    if(length(na.omit(x))) return(sum(x, na.rm = TRUE))
    NA
}
Run Code Online (Sandbox Code Playgroud)

我认为在大多数情况下,如果您只是在只有以下sum(x, na.rm = TRUE)情况时使用和测试,那么它应该是有效的:sum==0NA

sumna_c <- function(x) {
    ret <- sum(x, na.rm = TRUE)
    if(ret == 0 && all(is.na(x))) {NA} else {ret}
}
Run Code Online (Sandbox Code Playgroud)