我已经编写了一个函数来模拟遗传漂移,并且我希望将其循环到各种t值(代数)上,但是每当我这样做时,我都会收到以下错误:
locifreq<-runif(49, .4, 0.8)
gen<-1:100
for (i in 1:length(gen)){
pop[i]<-lapply(locifreq,wright.fisher,3000,200,gen[i])
}
Error in `[<-`(`*tmp*`, i, j, value = rbinom(1, 2 * N, prob = k[i - 1, :
subscript out of bounds
我认为这是因为我的功能无法生成适当的矩阵,或者它无法访问列表中的矩阵(尽管我可能完全错了!) ,但是我不确定如何解决这个问题,因为每次尝试都会导致下标数量不正确。
我的功能代码在
之下wright.fisher<-function(p,Ne,nsim,t){
N <-Ne/2
NA1 <- 2*N*p
NA2 <- 2*N*(1-p)
k <- matrix(0, nrow = t, ncol = nsim)
k[1,] <- rep(NA1, nsim)
for (j in 1:nsim) {
for (i in 2:t) {
k[i, j] <- rbinom(1, 2*N, prob = k[i-1, j] / (2*N))
}
}
k <- as.matrix(k/(2*N))
t(k)
}
有谁知道如何解决这个问题?
答案 0 :(得分:1)
使用此部分代码复制您的问题:
wright.fisher(locifreq[1], 3000, 200, 1)
导致下标越界错误的特定步骤是在循环的第一步中在第9行中分配k[i,j]
。此时,i
为2,j
为1.您通常可以通过将对象分配给超出其范围的索引来扩展对象,但是您无法通过在需要改变尺寸数量的方式。 (这是k[2,1]
当时所做的事情,因为它是1行和200列的矩阵。
k <- matrix(1:200, 1)
k[2,1] <- 5
# Error in `[<-`(`*tmp*`, 2, 1, value = 5) : subscript out of bounds
您可以通过让函数初始化矩阵以获得正确的维数来解决此问题。对功能的第5行进行更改
k <- matrix(0, nrow = max(2, t), ncol = nsim)
我之所以选择max(2, t)
,是因为这就是嵌套for循环的要求所强加的:for (i in 2:t)
。它完成,解决你的帖子中的问题,但请确认它产生你想要的行为。
此外,您的代码中有许多不是特别有效的习惯用语,但这是另一个问题。
如果你想知道如何调试这样的东西......我正在考虑编写一个关于如何使用浏览器的教程(这里经常出现)。在函数体顶部添加一行browser()
。然后,当您尝试运行浏览器时,它会在浏览器中将其拉出来,这样您就可以一次单步执行一个语句。输入help
以查看如何导航。在RStudio中,请继续关注“环境”选项卡以查看该变量的值。请注意,您可以在浏览器中评估任何R表达式。这将帮助您检查您认为导致问题的原因。
答案 1 :(得分:0)
你的Wright-Fisher模拟看起来有点复杂,但我不知道你在模拟什么,所以也许这是正确的。我会使用一个更简单的版本,只需在下一代中对基因频率进行采样,给出频率和有效种群大小。
target = [[1],[1]]
add = [2,4]
count = 0
idx = 0
while idx < len(target):
target[idx].append(add[idx])
idx += 1
print(target)
# >>>
[[1, 2], [1, 4]]
真正的问题是表以及如何索引它。如果wf <- function(f, Ne) {
rbinom(1, 2*Ne, prob = f) / (2*Ne)
}
计算给定wf
和f
的一个频率,并且您希望在Ne
代之间进行no_sims
次模拟,则可以构建no_gen
表格,填充它,使得行对应于世代,列对应于独立的模拟。它看起来像这样:
no_gens x no_sims
这些(小)参数的结果如下所示:
no_sims <- 5
no_gens <- 4
Ne <- 10000
locifreq <- runif(5, .4, 0.8)
sims <- matrix(NA, ncol = no_sims, nrow = no_gens)
sims[1,] <- runif(5, .4, 0.8) # first generation
for (gen in 2:no_gens) {
sims[gen,] <- sapply(sims[gen-1,], FUN = wf, Ne = Ne)
}