【问题标题】:There is pmin and pmax each taking na.rm, why no psum?有pmin和pmax各取na.rm,为什么没有psum?
【发布时间】:2012-10-29 14:31:44
【问题描述】:

R 似乎缺少一个明显的简单函数:psum。它是以不同的名称存在,还是在某个包中?

x = c(1,3,NA,5)
y = c(2,NA,4,1)

min(x,y,na.rm=TRUE)    # ok
[1] 1
max(x,y,na.rm=TRUE)    # ok
[1] 5
sum(x,y,na.rm=TRUE)    # ok
[1] 16

pmin(x,y,na.rm=TRUE)   # ok
[1] 1 3 4 1
pmax(x,y,na.rm=TRUE)   # ok
[1] 2 3 4 5
psum(x,y,na.rm=TRUE)
[1] 3 3 4 6                             # expected result
Error: could not find function "psum"   # actual result

我知道+ 已经像psum,但是NA 呢?

x+y                      
[1]  3 NA NA  6        # can't supply `na.rm=TRUE` to `+`

有加psum的情况吗?还是我错过了什么。

这个问题是这个问题的后续:
Using := in data.table to sum the values of two columns in R, ignoring NAs

【问题讨论】:

  • 启动倒计时,直到我们在 r-devel 上看到贡献的补丁:10,9,8,7,...
  • @DirkEddelbuettel:那个计时器到期了吗?
  • @DirkEddelbuettel 现在怎么样?
  • 一个答案可能只是function(...) { rowSums( cbind( ...) , na.rm=TRUE) }?应该使用适当尺寸的矢量或数据框的任何混合成功。当 na.rm=TRUE 时,NA、NA 的值为零,但sum 也是如此。从 1.9.6 版开始,仍然没有 data.table::psum
  • @DirkEddelbuettel 仍然没有?

标签: r


【解决方案1】:

在@JoshUlrich 对上一个问题的评论之后,

psum <- function(...,na.rm=FALSE) { 
    rowSums(do.call(cbind,list(...)),na.rm=na.rm) } 

编辑:来自 Sven Hohenstein:

psum2 <- function(...,na.rm=FALSE) { 
    dat <- do.call(cbind,list(...))
    res <- rowSums(dat, na.rm=na.rm) 
    idx_na <- !rowSums(!is.na(dat))
    res[idx_na] <- NA
    res 
}

x = c(1,3,NA,5,NA)
y = c(2,NA,4,1,NA)
z = c(1,2,3,4,NA)

psum(x,y,na.rm=TRUE)
## [1] 3 3 4 6 0
psum2(x,y,na.rm=TRUE)
## [1] 3 3 4 6 NA

n = 1e7
x = sample(c(1:10,NA),n,replace=TRUE)
y = sample(c(1:10,NA),n,replace=TRUE)
z = sample(c(1:10,NA),n,replace=TRUE)

library(rbenchmark)
benchmark(psum(x,y,z,na.rm=TRUE),
          psum2(x,y,z,na.rm=TRUE),
          pmin(x,y,z,na.rm=TRUE), 
          pmax(x,y,z,na.rm=TRUE), replications=20)

##                          test replications elapsed relative 
## 4  pmax(x, y, z, na.rm = TRUE)           20  26.114    1.019 
## 3  pmin(x, y, z, na.rm = TRUE)           20  25.632    1.000 
## 2 psum2(x, y, z, na.rm = TRUE)           20 164.476    6.417
## 1  psum(x, y, z, na.rm = TRUE)           20  63.719    2.486

Sven 的版本(可以说是正确的版本)要慢一些, 尽管它是否重要显然取决于应用程序。 有人想破解内联/Rcpp 版本吗?

至于为什么它不存在:不知道,但祝你好运让 R-core 做这样的添加......我不能随便想到一个足够广泛的 *misc 包,这可以去...

Matthew 在 r-devel 上的后续帖子在这里(似乎证实了):
r-devel: There is pmin and pmax each taking na.rm, how about psum?

【讨论】:

  • 那些不返回所需的结果。他们删除了NA。所需的结果是长度为 4 的向量:3 3 4 6.
  • 不是pdiff 因为psum(x,-y,na.rm=TRUE) 会这样做。也许ptimes 也是,但不是pdiv 也是出于同样的原因。但我猜psumptimes 更常见。
  • 刚刚从这个答案中检查了pminpmaxpsum 的表现。 3 个长度为 1e51e3 的向量的复制和结果非常相似:分别为 6.24、6.21、7.55 秒。虽然我发现很少有其他版本的 psum 有 30 个或更多。
  • @Julius,如果您愿意,请随时编辑我的答案(或发布您的基准作为答案)
  • 这个psum 函数是个好主意。仅添加一项:如果所有元素(在向量中的同一位置)都是NA(即使na.rm = TRUE),则psumpmax 都返回NA。检查pmin(NA, NA, na.rm = TRUE)。我稍微修改了您的函数以实现 psum 的相同行为:psum &lt;- function(...,na.rm=FALSE) { dat &lt;- do.call(cbind,list(...)); "[&lt;-"(rowSums(dat, na.rm=na.rm), rowSums(is.na(dat)) == ncol(dat), NA) }
【解决方案2】:

在 CRAN 上快速搜索后,至少有 3 个包具有psum 功能。 rccmiscincadatakitkit 似乎是最快的。下面重现了 Ben Bolker 的例子。

benchmark(
  rccmisc::psum(x,y,z,na.rm=TRUE),
  incadata::psum(x,y,z,na.rm=TRUE),
  kit::psum(x,y,z,na.rm=TRUE), 
  psum(x,y,z,na.rm=TRUE),
  psum2(x,y,z,na.rm=TRUE),
  replications=20
)
#                                    test replications elapsed relative
# 2 incadata::psum(x, y, z, na.rm = TRUE)           20   20.05   14.220
# 3      kit::psum(x, y, z, na.rm = TRUE)           20    1.41    1.000
# 4           psum(x, y, z, na.rm = TRUE)           20    8.04    5.702
# 5          psum2(x, y, z, na.rm = TRUE)           20   20.44   14.496
# 1  rccmisc::psum(x, y, z, na.rm = TRUE)           20   23.24   16.482

【讨论】:

    【解决方案3】:

    另一个优点是也可以使用矩阵,就像pminpmax

    psum <- function(..., na.rm = FALSE) {
      plus_na_rm <- function(x, y) ifelse(is.na(x), 0, x) + ifelse(is.na(y), 0, y)
      Reduce(if(na.rm) plus_na_rm else `+`, list(...))
    }
    
    x = c(1,3,NA,5)
    y = c(2,NA,4,1)
    
    psum(x, y)
    #> [1]  3 NA NA  6
    psum(x, y, na.rm = TRUE)
    #> [1] 3 3 4 6
    
    # With matrices
    A <- matrix(1:9, nrow = 3)
    B <- matrix(c(NA, 2:8, NA), nrow = 3)
    
    psum(A, B)
    #>      [,1] [,2] [,3]
    #> [1,]   NA    8   14
    #> [2,]    4   10   16
    #> [3,]    6   12   NA
    psum(A, B, na.rm = TRUE)
    #>      [,1] [,2] [,3]
    #> [1,]    1    8   14
    #> [2,]    4   10   16
    #> [3,]    6   12    9
    

    reprex package (v0.3.0) 于 2020 年 3 月 9 日创建

    一个警告:如果一个元素在所有求和对象中为NAna.rm = TRUE,则结果将为0(而不是NA)。

    例如:

    psum(NA, NA, na.rm = TRUE)
    #> [1] 0
    

    【讨论】:

    • 基础ifelseReduce?这将非常缓慢
    猜你喜欢
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 2014-04-12
    相关资源
    最近更新 更多