我想返回一个矩阵/ data.frame,每行包含参数和文件内容。
但是,可能有很多文件,所以我更喜欢我可以懒得加载文件,因此只有在请求实际内容时才会读取文件。如果as.func=F
。
如果它可以懒散地加载它们将是完美的,但是如果不是内容而是返回将读取内容的函数,那也是可以接受的。
我可以创建读取内容的函数(请参阅下面的as.func=T
),但出于某种原因,我无法将其放入data.frame中返回。
load_parallel_results <- function(resdir,as.func=F) {
## Find files called .../stdout
stdoutnames <- list.files(path=resdir, pattern="stdout", recursive=T);
## Find files called .../stderr
stderrnames <- list.files(path=resdir, pattern="stderr", recursive=T);
if(as.func) {
## Create functions to read them
stdoutcontents <-
lapply(stdoutnames, function(x) { force(x); return(function() { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } ) } );
stderrcontents <-
lapply(stderrnames, function(x) { force(x); return(function() { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } ) } );
} else {
## Read them
stdoutcontents <-
lapply(stdoutnames, function(x) { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } );
stderrcontents <-
lapply(stderrnames, function(x) { return(paste(readLines(paste(resdir,x,sep="/")),collapse="\n")) } );
}
if(length(stdoutnames) == 0) {
## Return empty data frame if no files found
return(data.frame());
}
## Make the columns containing the variable values
m <- matrix(unlist(strsplit(stdoutnames, "/")),nrow = length(stdoutnames),byrow=T);
mm <- as.data.frame(m[,c(F,T)]);
## Append the stdout and stderr column
mmm <- cbind(mm,unlist(stdoutcontents),unlist(stderrcontents));
colnames(mmm) <- c(strsplit(stdoutnames[1],"/")[[1]][c(T,F)],"stderr");
## Example:
## parallel --results my/res/dir --header : 'echo {};seq {myvar1}' ::: myvar1 1 2 ::: myvar2 A B
## > load_parallel_results("my/res/dir")
## myvar1 myvar2 stdout stderr
## [1,] "1" "A" "1 A\n1" ""
## [2,] "1" "B" "1 B\n1" ""
## [3,] "2" "A" "2 A\n1\n2" ""
## [4,] "2" "B" "2 B\n1\n2" ""
return(mmm);
}
背景
GNU Parallel有一个--results选项,以结构化方式存储输出。如果有1000000个输出文件,则可能很难管理它们。 R对此有好处,但如果你必须阅读所有1000000个文件只是为了获得参数1 =“Foo”和参数2 =“Bar”的那些文件,那将会非常慢。
答案 0 :(得分:3)
不幸的是,我不认为你可以在data.frame列中保存一个函数。 但是您可以存储函数的已解析文本并在需要时对其进行评估:
e.g。
myFunc <- function(x) { print(x) }
# convert the function to text
funcAsText <- deparse(myFunc)
# convert the text back to a function
newMyFunc <- eval(parse(text=funcAsText))
# now you can use the function newMyFunc exactly like myFunc
newMyFunc("foo")
> [1] "foo"
编辑:
由于文件很多,我建议您只需存储一个指示文件类型的字符串,并创建一个理解类型并相应读取文件的函数;所以你可以在需要时通过传递类型和文件路径来调用它。
答案 1 :(得分:2)
(不阅读问题正文:)
您可以像这样在data.frame
中存储函数:
df <- data.frame(fun = 1:3)
df$fun <- c(mean, sd, function(x) x^2)
我不确定这是否会破坏其他东西,因此请考虑从确实支持任意对象类型的相同命名包中使用tibble
或data.table
。
答案 2 :(得分:1)
您可以使用2D列表存储您的功能。显然,你失去了一些用DF获得的检查,但这就是重点:
> funs <- c(replicate(5, function(x) NULL), replicate(5, function(y) TRUE))
> names <- as.list(letters[1:10])
> # df doesn't work
> df <- data.frame(names=names)
> df.2 <- cbind(df, funs)
Error in as.data.frame.default(x[[i]], optional = TRUE) :
cannot coerce class ""function"" to a data.frame
# but 2d lists do
> lst.2d <- cbind(funs, names)
> lst.2d[2, 1]
$funs
function (x)
NULL
> lst.2d[6, 1]
$funs
function (y)
TRUE