尝试按具有4096列的数据帧(Camera1)中的行(690075)运行样条函数(每个列代表x轴上的位置),其中函数的输入变量是同一数据集的另一个数据集中的列使用for循环的长度(test $ vr);但我遇到了严重的计算时间问题。
我尝试将数据帧转换为矩阵并将输出存储在列表中,但无济于事。我必须对其他两个相同大小的数据帧(camera2,camera3)执行此操作。
代码
# Note camera1 and test$vr are of the same length
# Initialize
final.data1 <- data.frame()
#new wavelength range
y1 <- round(seq(from = 4714 , to = 4900, length.out = 4096),3)
system.time({
for (i in 1:690075) {
w1 = (as.numeric(colnames(camera1[-1]))) * (1.0 + test$vr[i]/299792.458)
my.data1<-as.data.frame(t(splinefun(x = w1, y = camera1[i,][-1])(y1)))
colnames(my.data1)=y1
final.data1 <- bind_rows(final.data1, my.data1)
} })
在具有344GB内存和30核心Intel(R)Xeon(R)CPU E5-2695 @ 2.30GHz的Ubuntu盒上运行
任何建议将不胜感激。 谢谢。
答案 0 :(得分:3)
不看数据,优化代码并不容易,但我将从以下内容开始。
final.data1 <- matrix(nrow = 690075, ncol = 4096)
#new wavelength range
y1 <- round(seq(from = 4714 , to = 4900, length.out = 4096), 3)
system.time({
w1 <- (as.numeric(colnames(camera1[-1]))) * (1.0 + test$vr/299792.458)
for (i in 1:690075) {
my.data1 <- t(splinefun(x = w1[i], y = camera1[i, ][-1])(y1))
final.data1[i, ] <- my.data1
}
})
final.data1 <- as.data.frame(final.data1)
colnames(final.data1) <- y1
说明:
我首先定义一个类matrix
的对象来保存结果。我相信我对您的最终data.frame
的理解正确。这样可以减少运行时间,因为
矩阵比数据帧快得多,它们只是折叠的矢量,索引也很快。相反,数据框是可以容纳所有类型的数据,数字,字符,逻辑,其他列表等的列表,因此访问它们的成员很慢。
通过在一个操作中保留结果的全部内存,可以节省R的内存管理例程的大量工作。要扩展final.data1
遍历循环,非常耗时。
w1
是在循环外部使用R的矢量化性质计算的。此外,您重复了as.numeric(colnames(camera1[-1]))
690k次的计算!
测试这段代码,如果它不能产生相同的最终结果,只需说一遍,我就会看看是否可以做一些调试工作。
答案 1 :(得分:3)
首先删除所有只能执行一次的指令,然后将其置于for循环之外。例如:colnames
和as.numeric
。
第二,尝试向量化。看来w1
的计算可以向量化,因此只需删除[i]
就可以在for循环外进行估算。
第三,将final.data1
初始化为最终尺寸。对于添加到此data.frame的每一行,R将创建一个新的data.frame并增加一行,然后删除先前的data.frame。这将需要很长时间。因此,final.data1 <- matrix(NA, ncol=length(y1), nrow=NROW)
。
最后,如果要使用多个内核,请尝试用并行化的foreach loop
替换for循环。所有行都可能是独立的:
require(foreach)
require(doSNOW)
cl <- makeCluster(25, type="FORK") # FORK not usable in Windows
registerDoSNOW(cl) # register the cluster
clusterExport(cl, c("objects", "needed", "by", "each", "iteration"), envir=environment()) # for example y1, w1 and camera1
final.data1<- foreach(i=icount(NROW), .combine=rbind, inorder=FALSE) %dopar%
{
# your R code
}
stopCluster(cl)