模拟R中直方图二项波动的零计数箱

模拟R中直方图二项波动的零计数箱,r,statistics,simulation,R,Statistics,Simulation,我有一个观察到的垃圾箱计数直方图。我想根据观察到的计数进行模拟,看看相同数量的观察结果可能会有什么不同。我将直方图转换为一个向量,将观察到的计数作为向量的一个元素。我使用二项式分布生成的随机数(来自rbinom(n,size,prob))模拟每个箱子,概率基于箱子频率 我的问题是模拟观察计数为零的垃圾箱。当箱子计数为零时,prob=0,因此该箱子的模拟计数始终为零。这是非物质的,不是我想要的。目前,我处理这个问题的方法是用1的bin counts覆盖零bin counts。我不确定这会有什么影响

我有一个观察到的垃圾箱计数直方图。我想根据观察到的计数进行模拟,看看相同数量的观察结果可能会有什么不同。我将直方图转换为一个向量,将观察到的计数作为向量的一个元素。我使用二项式分布生成的随机数(来自
rbinom(n,size,prob)
)模拟每个箱子,概率基于箱子频率

我的问题是模拟观察计数为零的垃圾箱。当箱子计数为零时,
prob
=0,因此该箱子的模拟计数始终为零。这是非物质的,不是我想要的。目前,我处理这个问题的方法是用1的bin counts覆盖零bin counts。我不确定这会有什么影响,所以我不知道我的模拟是否偏离了我的公差范围。我正在寻找一个比我的临时方法更好或更优雅的解决方案

有什么想法吗?多谢各位

这是我的相关代码:

sim.vector <- function(x, n = length(x)) {
  sum.vector <- round(sum(x), 0)  # the number of observations
  x.dummy <- x
  x.dummy[x.dummy == 0] <- 1  # override bins with zero counts
  f <- x.dummy / sum(x) # the frequency of each bin
  x.sim <- rep(0, n)
  while(sum.vector != sum(x.sim)) {  # make sure the simulation has the same
                                     # number of total counts as the observation
    for (i in 1:n) {
      p.target <- f[i]  # set the probability of each bin to the frequency
      x.sim[i] <- rbinom(1, sum.vector, p.target)  # create a random binomial
    }
  }
  return(x.sim)
}

sim.vector您尝试执行的操作听起来很像引导,如果您从n个值的数组开始,您将从该数组中随机选择n个值,并进行替换。正如您所注意到的,引导不会给您一个您还没有的价值

您可以选择设置零箱的方法。生态学家使用的一种技术是将零值设置为他们可能产生的最小测量误差。例如,如果计算树,最小错误计数为1。如果保持分布的平均值对您很重要,请确保将0更改为1不会使平均值增加太多

另一个选择是使用参数化分布来适应您的箱子。你所在领域的人是否有他们使用的典型分布,或者数据是否表明存在分布?如果仍然需要存储箱,可以存储拟合的参数化分布。祝你好运

以下是生成垃圾箱数量的更快方法:

# you have three bins which we label 1,2,3
# change to 1:n where n = number of your bins
binIndex = 1:3
# you have 2 values in bin 1, 3 values in bin 2, 1 value in bin 3
count1 = c(2,3,1)

# create a vector with all bin labels
unbin = mapply(function(bin1,ct1){
    rep(bin1,times=ct1)
},binIndex,count1)

unbin = unlist(unbin)
print(unbin)

# generate "bootstrapBinCount" of bootstrapped bins
bootstrapBinCount = 10

# in general, use lapply instead of while/for loops in R - it's orders of magnitude faster
# newBins is a list of binCounts
# to access the first bin count, try newBins[[1]]
newBins = lapply(1:bootstrapBinCount,function(x){
    # generate a bootstrap from the list of bin labels by sampling with replacement
    bootstrap1 = sample(unbin, size=length(unbin), replace = TRUE)
    # count the number of times each bin label shows up
    rebin = table(bootstrap1)
    # get the names of the labels that showed up
    names1 = as.integer(names(rebin))
    # fill in the counts from rebin, but also include cases where there are no values     for a given bin label
    rebinPlusZeroes = rep(0,times=length(binIndex))
    rebinPlusZeroes[names1] = as.integer(rebin)

    return(rebinPlusZeroes)
})

print(str(newBins))

在频率估计中处理零计数的问题有时被称为平滑(特别是在自然语言处理社区中,它们处理数千个“箱子”,因此零计数很常见);不使用计数,而是使用

一个简单的方法与您正在做的类似:只需在每个容器中添加一个(而不仅仅是零)。一般来说,您可以在中添加不同的数字(通常小于一)。在贝叶斯理论中,这相当于在二项式概率上使用狄里克莱先验

更复杂的方法是


如果您的数据有一个不同的概率模型,在您的设置中更有意义,您也可以使用它(正如Eric所建议的)。

有多少个箱子(
n
)?我猜是2,但你永远不知道。:)我不确定我是否理解得很好,但请尝试以下操作:
sample.int(n,size=sum(x),replace=TRUE,prob=f)
看看它是否能带您到某个地方。
n
可以是任何整数。通常,对于我正在进行的模拟,它在2到6之间。
sample.int
看起来很有趣;我以前从未用过。我不确定我是否理解正确。就我的情况来说,假设我在掷硬币
x
是结果的向量,比如说,
x感谢
sample.int
指针。它通过避免
while
for
循环来加快速度。我现在可以使用
x.sim了