【问题标题】:Why am I getting NAs in this calculation in R?为什么我在 R 的这个计算中得到 NA?
【发布时间】:2021-01-25 21:17:02
【问题描述】:

在处理 Rcpp 程序时,我使用了 sample() 函数,它给了我以下错误:“NAs not allowed in probability.”我将此问题追溯到我使用的概率向量中包含 NA 值的事实。我不知道怎么做。下面是一些捕获错误的 R 代码:

n.0=20
n.1=20
n.reps=1
beta0.vals=rep(seq(-.3,.1,,n.0),n.reps)
beta1.vals=rep(seq(-7,0,,n.1),n.reps)
beta.grd=as.matrix(expand.grid(beta0.vals,beta1.vals))

n.rnd=200
beta.rnd.grd=cbind(runif(n.rnd,min(beta0.vals),max(beta0.vals)),runif(n.rnd,min(beta1.vals),max(beta1.vals)))
beta.grd=rbind(beta.grd,beta.rnd.grd)
  
N = 22670
count = 0

for(i in 1:dim(beta.grd)[1]){ # iterate through 600 possible beta values in beta grid
    
  beta.ind = 0 # indicator for current pair of beta values
    
  for(j in 1:N){ # iterate through all possible Nsums
    logit = beta.grd[i,1]/N*(j - .1*N)^2 + beta.grd[i,2];
    phi01 = exp(logit)/(1 + exp(logit))
      
    if(is.na(phi01)){ 
      count = count + 1
    }
  }
}

cat("Total number of invalid probabilities: ", count)

这里,$\beta_0 \in (-0.3, 0.1), \beta_1 \in (-7, 0), N = 22670, N_\text{sum} \in (1, N)$。注意 $N$$N_\text{sum}$ 是整数,而 beta 值可能不是。

由于在数学上,$\phi_{01} \in (0,1)$,我假设 NA 的出现是因为 R 不喜欢极小价值观。我也收到了大量的 NA 值。比数字更重要。为什么我会在这段代码中得到 NA?

【问题讨论】:

  • 一个可运行的示例会有所帮助。另外,第一行的除法和乘法是否按照您想要的顺序?
  • 这确实不属于这里,但是在stackoverflow上,我们可以为您迁移它,但首先您需要制作一个可重现(即只需复制代码即可运行)的示例。
  • 同时,为了不收集误导性的回复,最好将其关闭。一旦进行了编辑,社区就会注意到这一点并可以进行迁移。或者,直接在Stack Overflow 上发布您的问题。抄送@Kjetil
  • @kjetilbhalvorsen 我添加了可重现的代码(在 R 中,而不是在 Rcpp 中)

标签: r probability missing-data


【解决方案1】:

count = count + 1 旁边包含print(logit),您会发现很多logit > 1000 值。 exp(1000) == Inf 所以你将Inf 除以Inf 得到NaNNaNNA

> exp(500)
[1] 1.403592e+217
> Inf/Inf
[1] NaN
> is.na(NaN)
[1] TRUE

因此,您的问题不是太小,而是从exp(x) 的评估中首先出现的大量问题x 大于大约 700:

> exp(709)
[1] 8.218407e+307
> exp(710)
[1] Inf

【讨论】:

  • 哦,哇。感谢您指出了这一点。有没有办法可以将 exp(1000) 强制为双精度值或将保持值而不是 Inf 的值?也许减小 N 的大小也可以缓解这个问题,但我希望 N 尽可能大。
  • phi01 = exp(min(logit,709))/(1 + exp(min(logit,709))) 会这样做,除非您需要 phi01 以避免四舍五入为 0 或 1
  • @Henry 感谢您提供这个快速技巧!
【解决方案2】:

Bernhard's answer 正确识别问题: 如果logit 很大,则exp(logit) = Inf。 这是一个解决方案:

for(i in 1:dim(beta.grd)[1]){ # iterate through 600 possible beta values in beta grid
    
    beta.ind = 0 # indicator for current pair of beta values
    
    for(j in 1:N){ # iterate through all possible Nsums
        logit = beta.grd[i,1]/N*(j - .1*N)^2 + beta.grd[i,2];
        ## This one isn't great because exp(logit) can be very large
        # phi01 = exp(logit)/(1 + exp(logit))
        ## So, we say instead
        ## phi01 = 1 / ( 1 + exp(-logit) )
        phi01 = plogis(logit)
        
        
        if(is.na(phi01)){ 
            count = count + 1
        }
    }
}

cat("Total number of invalid probabilities: ", count)
# Total number of invalid probabilities:  0

我们可以使用更稳定的1 / (1 + exp(-logit) (为了让自己相信这一点,请将您的表达式乘以exp(-logit) / exp(-logit)), 幸运的是,无论哪种方式,R 都有一个内置函数plogis(),可以快速准确地计算这些概率。 您可以从帮助文件 (?plogis) 中看到,此函数会计算我给出的表达式,但您也可以仔细检查以确保自己

x = rnorm(1000)
y = 1 / (1 + exp(-x))
z = plogis(x)
all.equal(y, z)
[1] TRUE

【讨论】:

  • 非常好的收获!
  • @DirkEddelbuettel 实际上,我在统计培训的早期就已经处理过这个确切的问题,即(1)遇到 OP 的问题,然后(2)找出更稳定的方法来解决通过数学编码问题,然后很多稍后(3)意识到R当然已经有一个内置函数
  • 这里的相关部分是 但当然 R 已经涵盖了它 ...
  • @DirkEddelbuettel 是的,是的,是的。 100 次中有 99 次,你绞尽脑汁想办法解决问题,却发现其他开发人员(通常是 R Core)已经为你解决了问题
  • 我投了赞成票,因为这避免了NA。但是,对于原始发布者问题中x 的值,1/(1+exp(-x)) 将产生大量零作为1/Inf == 0 的结果。大量零中的信息不是和NA中的信息一样小吗? NA 可以告诉您,R 无法计算您想要计算的内容。零可能会误导您并延长出错时间,直到您对结果进行进一步计算。
猜你喜欢
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
  • 2023-01-12
  • 2021-04-11
  • 1970-01-01
  • 2017-09-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多