从密度对象生成随机数(或更广泛地从一组数字生成)

时间:2013-06-13 12:39:45

标签: r random

我们假设我有一组我怀疑来自同一发行版的数字。

set.seed(20130613)
x <- rcauchy(10)

我想要一个从同一个未知发行版中随机生成数字的函数。我想到的一种方法是创建一个density对象,然后从中获取CDF并获取随机统一变量(see Wikipedia)的反向CDF。

den <- density(x)

#' Generate n random numbers from density() object
#' 
#' @param n The total random numbers to generate
#' @param den The density object from which to generate random numbers
rden <- function(n, den)
{
        diffs <- diff(den$x)
        # Making sure we have equal increments
        stopifnot(all(abs(diff(den$x) - mean(diff(den$x))) < 1e-9))
        total <- sum(den$y)
        den$y <- den$y / total
        ydistr <- cumsum(den$y)
        yunif <- runif(n)
        indices <- sapply(yunif, function(y) min(which(ydistr > y)))
        x <- den$x[indices]

        return(x)
}

rden(1, den)
## [1] -0.1854121

我的问题如下:

  1. 是否有更好的(或内置于R)方式从密度对象生成随机数?
  2. 关于如何从一组数字生成随机数(除sample之外)还有其他想法吗?

3 个答案:

答案 0 :(得分:10)

要从密度估计生成数据,您只需随机选择一个原始数据点,并根据密度估计中的内核添加随机“错误”片段,默认为“高斯”这只是意味着选择随机来自原始向量的元素并添加一个随机法线,其均值为0,sd等于所使用的带宽:

den <- density(x)

N <- 1000
newx <- sample(x, N, replace=TRUE) + rnorm(N, 0, den$bw)

另一种选择是使用logspline包中的logspline函数拟合密度(使用另一种估算密度的方法),然后使用该包中的rlogspline函数从估计的密度生成新数据。

答案 1 :(得分:2)

如果您只需要从现有的数字池中提取值,那么sample就是您的选择。
如果要从假定的基础分布中绘制,则使用density,并将其与假定的分布拟合,以获得必要的系数(均值,sd等),并使用适当的R分布功能

除此之外,我将看一下C中Numerical Recipes的第7.3章(“拒绝方法”),了解根据任何分布“选择性地”采样的方法。代码很简单,可以轻松转换为R。 我敢打赌,有人已经这样做,并会发布一个比这更好的答案。

答案 2 :(得分:0)

Greg Snow 的回答对我很有帮助,我意识到密度函数的输出具有从输入分布创建随机数所需的所有数据。基于他的示例,您可以执行以下操作以使用密度输出获取随机值。

x <- rnorm(100)   # or any numeric starting vector you desire
dens <- density(x)
N <- 1000
newx <- sample(x = dens$x, N, prob = dens$y, replace=TRUE) + rnorm(N, 0, dens$bw)

你甚至可以创建一个简单的随机数生成函数

rdensity <- function(n, dens) {
    return(sample(x = dens$x, n, prob = dens$y, replace=TRUE) + rnorm(n, 0, dens$bw))
}