我正在尝试实施一个块引导程序,但我还没有找到一种有效的方法。
我的data.frame具有以下结构:
CHR POS var_A var_B
1 192 0,9 0,7
1 2000 0,8 0,3
2 3 0,21 0,76
2 30009 0,36 0,15
...
第一列是染色体识别,第二列是位置,最后两列是我想要计算相关性的变量。问题是每一行并不是完全独立的,取决于它们之间的距离(越接近越依赖),所以我不能简单地做cor(df$var_A, df$var_B)
。
这种类型数据常用的问题是执行块引导程序。也就是说,我需要将数据划分为长度为X的块,随机选择该块内的一行,然后计算我感兴趣的统计量。但请注意,这些块需要根据列POS进行定义,而不是基于行号。此外,需要对每条染色体进行此程序。
我试图实现这一点,但我想出了最慢的代码(它甚至没有完成运行)并且我不是100%确定它是否有效。
x = 1000
cors = numeric()
iter = 1000
for(j in 1:iter) {
df=freq[0,]
for (i in unique(freq$CHR)) {
t = freq[freq$CHR==i,]
fim = t[nrow(t),2]
i = t[1,2]
f = i + x
while(f < fim) {
rows = which(t$POS>=i & t$POS<f)
s = sample(rows)
df = rbind(df,t[s,])
i = f
f = f + x
}
}
cors = c(cors, cor(df$var_A, df$var_B))
}
有人可以帮帮我吗?我相信有一种更有效的方法。
提前谢谢。
答案 0 :(得分:1)
我希望我理解你:
# needed for round_any()
library(plyr)
res <- lapply(unique(freq$CHR),function(x){
freq_sel <- freq[freq$CHR==x,]
blocks <- lapply(seq(1,round_any(max(freq_sel$POS),1000,ceiling),1000), function(ix) freq_sel[freq_sel$POS > ix & freq_sel$POS <= ix+999,])
do.call(rbind,lapply(blocks,function(x) if (nrow(x) > 1) x[sample(1:nrow(x),1),] else x))
})
这应返回一个列表,其中包含每条染色体的条目。在每个条目中,如果存在,则每1kb块进行一次观察。块数由最大POS
值确定。
library(doParallel)
library(foreach)
library(plyr)
cl <- makeCluster(detectCores())
registerDoParallel(cl)
res <- foreach(x=unique(freq$CHR),.packages = 'plyr') %dopar% {
freq_sel <- freq[freq$CHR==x,]
blocks <- lapply(seq(1,round_any(max(freq_sel$POS),1000,ceiling),1000), function(ix) freq_sel[freq_sel$POS > ix & freq_sel$POS <= ix+999,])
do.call(rbind,lapply(blocks,function(x) if (nrow(x) > 1) x[sample(1:nrow(x),1),] else x))
}
stopCluster(cl)
这是每个染色体上foreach
的简单并行化。重构函数并将并行处理基于另一个级别(例如1000次迭代或可能是块)可能更好。在任何情况下,我都可以再次强调我在评论中所说的内容:在您对代码进行并行化之前,您应该确保它尽可能高效。这意味着您可能需要查看boot
包或类似内容以提高效率。也就是说,根据您计划的迭代次数,一旦您熟悉您的功能,并行处理可能会很有用。
答案 1 :(得分:1)
尝试的一种有效方法是使用'boot'包,其功能包括并行处理功能。
特别是,'tsboot'或时间序列引导功能将选择有序的数据块。如果您的POS
变量是某种有序观察,这可能会有效。
启动包功能很棒,但首先需要一些帮助。要在引导包中使用引导函数,必须首先在包含index
参数的函数中包装感兴趣的统计信息。这是bootstrap生成的索引将用于将采样数据传递给统计信息的设备。
cor_hat <- function(data, index) cor(y = data[index,]$var_A, x = data[index,]$var_B)
请注意以下参数中的cor_hat
。 sim = "fixed", l = 1000
个参数,表示您需要fixed
个长度的块(l
)1000
。但是,如果你试图捕捉随时间推移的最近邻居动态,你可以做任何大小的块,5或10。 multicore
参数说明了一切,但如果您使用的是Windows,它可能会“下雪”。
library(boot)
tsboot(data, cor_hat, R = 1000, sim = "fixed", l = 1000, parallel = "multicore", ncpus = 4)
此外,统计学习要素的第194页提供了使用传统boot
函数的框架的一个很好的例子,所有这些都与tsboot
相关。 / p>
希望有所帮助,祝你好运。
贾斯汀
答案 2 :(得分:0)
所以,过了一会儿,我想出了一个问题的答案。在这里。
您需要包dplyr
。
l = 1000
teste = freq %>%
mutate(w = ceiling(POS/l)) %>%
group_by(CHR, w) %>%
sample_n(1)
此代码根据基因组中的位置(POS)创建一个名为w
的新变量。此变量w
是指定每行的窗口,它取决于l
,即窗口的长度。
您可以多次重复此代码,每次每个窗口采样一行/ CHR(使用sample_n(1)
)并应用您想要的任何感兴趣的统计数据。