首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R-使用Inf或Null

R-使用Inf或Null
EN

Stack Overflow用户
提问于 2014-09-17 23:29:05
回答 1查看 79关注 0票数 1

我经常在R中编写函数,理论上,参数应该缺省为Inf或-Inf。但是,将参数默认为NULL并检查是否为该参数提供了值也是有意义的。例如,考虑以下两个函数

代码语言:javascript
复制
myfunc <- function(numVec, cap=NULL){
  if(!is.null(cap)) numVec <- pmin(numVec, cap)
  return(sum(numVec) + mean(numVec))
}

myfunc <- function(numVec, cap=Inf){
  numVec <- pmin(numVec, cap)
  return(sum(numVec) + mean(numVec))
}

对于相同的输入,它们将始终返回相同的结果。但是哪一种设计更好呢?第一种方法可能比第二种方法的效率稍高一些,但第二种方法更优雅。显然,这是一个非常简单的例子,但是当面对这个设计决策时,有没有人有一些好的经验法则呢?

EN

回答 1

Stack Overflow用户

发布于 2014-09-18 00:10:08

我不确定这是否构成了一个答案,但这篇评论太长了,也许会有所帮助。

内存中的大小

代码语言:javascript
复制
require(pryr)

object_size(Inf)
# 48 B
object_size(NULL)
# 0 B

基准测试

代码语言:javascript
复制
require(microbenchmark)

numVec2 <- numVec1 <- 1:3
cap1.1 <- Inf
cap2.1 <- NULL
cap2.2 <- cap1.2 <- 2
ex1.1 <- expression({ numVec1 <- pmin(numVec1, cap1.1); numVec1 })
ex1.2 <- expression({ numVec1 <- pmin(numVec1, cap1.2); numVec1 })
ex2.1 <- expression({ if(!is.null(cap2)) numVec2 <- pmin(numVec2, cap2.1); numVec2 })
ex2.2 <- expression({ if(!is.null(cap2)) numVec2 <- pmin(numVec2, cap2.2); numVec2 })

microbenchmark(ex1.1, ex1.2, ex2.1, ex2.2, times = 1000)
# Unit: nanoseconds
#   expr min   lq median    uq   max neval
#  ex1.1  42 46.5     50 116.5 33841  1000
#  ex1.2  40 46.0     49 117.5 23931  1000
#  ex2.1  42 48.0     52 116.0 28167  1000
#  ex2.2  47 53.0     55 122.0  3014  1000

分析

代码语言:javascript
复制
require(lineprof)

lp1.1 <- lineprof(eval(ex1.1), torture = TRUE)
lp1.2 <- lineprof(eval(ex1.2), torture = TRUE)
lp2.1 <- lineprof(eval(ex2.1), torture = TRUE)
lp2.2 <- lineprof(eval(ex2.2), torture = TRUE)

lp1.1
# Reducing depth to 2 (from 5)
#    time alloc release dups               ref       src
# 1 0.001 0.001   0.000    0      character(0)          
# 2 0.007 0.001   0.005    0            "eval" eval     
# 3 0.011 0.003   0.003    5 c("eval", "eval") eval/eval
lp1.2
# Reducing depth to 2 (from 5)
#    time alloc release dups               ref       src
# 1 0.001 0.001   0.000    0      character(0)          
# 2 0.012 0.004   0.001    5 c("eval", "eval") eval/eval
lp2.1
#    time alloc release dups          ref src
# 1 0.002     0       0    0 character(0)    
lp2.2
#    time alloc release dups               ref       src
# 1 0.001     0       0    0 c("eval", "eval") eval/eval
# 2 0.001     0       0    0      character(0)

因此,检查!is.null(caps)似乎(毫不奇怪)总体上比让pmin处理Inf要高效得多。因此,在超高效代码和数学优雅之间存在权衡。

然而,事实证明,检查cap != Inf比检查!is.null(cap)更快

代码语言:javascript
复制
microbenchmark(!is.null(cap2.1), cap1.1 != Inf, times = 1000)
# Unit: nanoseconds
#              expr min  lq median  uq  max neval
#  !is.null(cap2.1) 130 145    152 203 4660  1000
#     cap1.1 != Inf  87 100    107 155 1317  1000

所以事实证明,在这种情况下,你可以既吃蛋糕又吃蛋糕:

代码语言:javascript
复制
myfunc <- function (numVec, cap = Inf) {
  if(cap != Inf) numVec <- pmin(numVec, cap)
  sum(numVec) + mean(numVec)
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25894643

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档