在 *apply 中退出一个函数
Exit a function within *apply
sapply
和 replicate
(等)运行 指定的次数。放sapply(1:N, function(n){expr})
会执行expr
N次。假设我希望 sapply
在 m 运行 秒后停止。这有可能不出错吗? break
不起作用,for
或 while
循环在我的上下文中太慢了。
类似于:
sapply(1:N, function(n){
#some expression
if(identical(n, m)) break
})
除了 break 不起作用。
我想做什么:
创建一个函数来读取已定义结构但长度未知的大型(二进制)数据文件。使用 replicate
和 array(readBin(...), ...)
是我发现的最好的方法,但我希望它在 NA
开始返回时停止(即到达文件末尾) .
除了 for
与 *apply
的战斗之外,如果您的问题是使用 readBin
直到到达文件末尾,请记住:
- 您可以(小)高估
n
(要读取的元素数);
- 通过
file.info(filename)$size
可以知道文件的大小;那么你可以自己估算一下文件中包含了多少个元素。
例如,假设您正在读取整数(四个字节)值。试试看:
readBin(con,"int",n=file.info(filename)$size/4+10)
一次读取所有文件。 +10
是高估了一点
可以以全局控制变量的形式使用部分解决方法
i<-TRUE
unlist( sapply(1:10, function(x){if(i){ if(x>=4)(i<<-FALSE); 2*x;}}) )
虽然还是跑了n次,但至少不是每次都执行操作,节省资源。
而且我无法完全弄清楚为什么简化一直没有奏效,我不得不使用 unlist。
以为我会 post 我为此想到了什么。 cbb
是正在构建的数组。在坏的例子中,cbb
使用 abind
逐渐构建为数组。在每一步,cbb
都必须重新评估,因此每个连续的步骤都比较慢 - 一个不断增长的对象。在这个好例子中,cbb
被构建为一个列表,并且每一步都会声明一个新的列表条目。 R 不需要每次都重新评估现有列表。该数组在末尾用 do.call(abind, c(cbb, list(along = 4)))
.
绑定在一起
我觉得有帮助的一件事是将 cat(".")
放在循环中。如果点打印速度减慢,则可能表示物体正在生长。在这个好例子中,点的打印速度或多或少是恒定的。好的例子比坏的例子快十倍。
差:
cbb <- array(NA, c(N1, N2, N3, 0))
repeat{
sptsnew <- readBin(to.read, "integer", 2L, 4L)
if(identical(sptsnew, integer(0))){cat("\nend of file\n"); break}
... #reading array metadata
cbb <- abind(cbb, array(readBin(to.read, "double", N1*N2*N3, 4L), c(N1, N2, N3, 1)), along = 4)
cat(".")
}
好:
i <- 1
cbb <- list()
repeat{
sptsnew <- readBin(to.read, "integer", 2L, 4L)
if(identical(sptsnew, integer(0))){cat("\nend of file\n"); break}
... #reading array metadata
cbb[[i]] <- array(readBin(to.read, "double", N1*N2*N3, 4L), c(N1, N2, N3, 1))
i <- i + 1
cat(".")
}
cbb <- do.call(abind, c(cbb, list(along = 4)))
sapply
和 replicate
(等)运行 指定的次数。放sapply(1:N, function(n){expr})
会执行expr
N次。假设我希望 sapply
在 m 运行 秒后停止。这有可能不出错吗? break
不起作用,for
或 while
循环在我的上下文中太慢了。
类似于:
sapply(1:N, function(n){
#some expression
if(identical(n, m)) break
})
除了 break 不起作用。
我想做什么:
创建一个函数来读取已定义结构但长度未知的大型(二进制)数据文件。使用 replicate
和 array(readBin(...), ...)
是我发现的最好的方法,但我希望它在 NA
开始返回时停止(即到达文件末尾) .
除了 for
与 *apply
的战斗之外,如果您的问题是使用 readBin
直到到达文件末尾,请记住:
- 您可以(小)高估
n
(要读取的元素数); - 通过
file.info(filename)$size
可以知道文件的大小;那么你可以自己估算一下文件中包含了多少个元素。
例如,假设您正在读取整数(四个字节)值。试试看:
readBin(con,"int",n=file.info(filename)$size/4+10)
一次读取所有文件。 +10
是高估了一点
可以以全局控制变量的形式使用部分解决方法
i<-TRUE
unlist( sapply(1:10, function(x){if(i){ if(x>=4)(i<<-FALSE); 2*x;}}) )
虽然还是跑了n次,但至少不是每次都执行操作,节省资源。 而且我无法完全弄清楚为什么简化一直没有奏效,我不得不使用 unlist。
以为我会 post 我为此想到了什么。 cbb
是正在构建的数组。在坏的例子中,cbb
使用 abind
逐渐构建为数组。在每一步,cbb
都必须重新评估,因此每个连续的步骤都比较慢 - 一个不断增长的对象。在这个好例子中,cbb
被构建为一个列表,并且每一步都会声明一个新的列表条目。 R 不需要每次都重新评估现有列表。该数组在末尾用 do.call(abind, c(cbb, list(along = 4)))
.
我觉得有帮助的一件事是将 cat(".")
放在循环中。如果点打印速度减慢,则可能表示物体正在生长。在这个好例子中,点的打印速度或多或少是恒定的。好的例子比坏的例子快十倍。
差:
cbb <- array(NA, c(N1, N2, N3, 0))
repeat{
sptsnew <- readBin(to.read, "integer", 2L, 4L)
if(identical(sptsnew, integer(0))){cat("\nend of file\n"); break}
... #reading array metadata
cbb <- abind(cbb, array(readBin(to.read, "double", N1*N2*N3, 4L), c(N1, N2, N3, 1)), along = 4)
cat(".")
}
好:
i <- 1
cbb <- list()
repeat{
sptsnew <- readBin(to.read, "integer", 2L, 4L)
if(identical(sptsnew, integer(0))){cat("\nend of file\n"); break}
... #reading array metadata
cbb[[i]] <- array(readBin(to.read, "double", N1*N2*N3, 4L), c(N1, N2, N3, 1))
i <- i + 1
cat(".")
}
cbb <- do.call(abind, c(cbb, list(along = 4)))