问题
This is a question raised in the context of this other one: Extract and paste together multiple columns of a data frame like object using a vector of column names
I received an answer based on the usage of do.call
which happens to not work when the code is part of a library, but worked well when implemented as part of the main script.
Here is my attempt at making a simplified example:
File example.do.call.R
:
library(S4Vectors)
library(test.package)
data <- DataFrame(A=letters[1:6], B=LETTERS[1:6])
test_do_paste <- function(data) {
groups <- c("A", "B")
combined_letters <- do.call(paste, data[groups])
print(combined_letters)
}
test_do_paste(data)
#test.package::test_do_paste(data)
The same test_do_paste
function is present as a single function in a package I organize and install according to https://hilaryparker.com/2014/04/29/writing-an-r-package-from-scratch/.
When running Rscript example.do.call.R
as above, I obtain the expected result:
[1] "a A" "b B" "c C" "d D" "e E" "f F"
However, if I switch to the commented version (using the function from the library), I get the following error:
Error in do.call(paste, data[groups]) : second argument must be a list
Calls: <Anonymous> -> do.call
Execution halted
My questions are:
Why is that?
How can I avoid the error?
Some investigation
I used a normal data.frame
instead of the DataFrame
In this case, the error doesn't happen.
Note that in my real application, I'm actually using some more complicated object than a DataFrame, but there is a colData
function that extracts a DataFrame
from this object.
Maybe there would be a way to circumvent the problem if I was able to convert this further into a normal data.frame
.
as.data.frame
actually does this, so question 2 has at least this solution in my case.
I inserted a print(class(data[groups]))
in the function
In both cases I get the following:
[1] "DataFrame"
attr(,"package")
[1] "S4Vectors"
So, apparently, even in the case that works, the object I give as second argument to do.call
is not a list.
I inserted a print(do.call)
in the function.
When run from the library, I obtain just a few lines:
function (what, args, quote = FALSE, envir = parent.frame())
{
if (!is.list(args))
stop("second argument must be a list")
if (quote)
args <- lapply(args, enquote)
.Internal(do.call(what, args, envir))
}
<bytecode: 0x1b7cdd8>
<environment: namespace:base>
But when run in the script, there is much more output:
function (what, args, quote = FALSE, envir = parent.frame())
standardGeneric("do.call")
<environment: 0x1d8c568>
attr(,"generic")
[1] "do.call"
attr(,"generic")attr(,"package")
[1] "BiocGenerics"
attr(,"package")
[1] "BiocGenerics"
attr(,"group")
list()
attr(,"valueClass")
character(0)
attr(,"signature")
[1] "what" "args"
attr(,"default")
Method Definition (Class "derivedDefaultMethod"):
function (what, args, quote = FALSE, envir = parent.frame())
{
if (!is.list(args))
stop("second argument must be a list")
if (quote)
args <- lapply(args, enquote)
.Internal(do.call(what, args, envir))
}
<bytecode: 0x1d8e660>
<environment: namespace:base>
Signatures:
what
target "ANY"
defined "ANY"
attr(,"skeleton")
(function (what, args, quote = FALSE, envir = parent.frame())
{
if (!is.list(args))
stop("second argument must be a list")
if (quote)
args <- lapply(args, enquote)
.Internal(do.call(what, args, envir))
})(what, args, quote, envir)
attr(,"class")
[1] "standardGeneric"
attr(,"class")attr(,"package")
[1] "methods"
This raises more questions:
Why this difference?
Could it explain the error in the "library" case?
来源:https://stackoverflow.com/questions/40807266/do-call-error-second-argument-must-be-a-list-with-s4vectors-when-the-code-is-i