If I do:
file.path("", "a", "b", "c.txt")
[1] "/a/b/c.txt"
I got the correct file path, but if I do this way:
cc<-c("", "a", "b", "c.txt")
file.path(cc)
[1] "" "a" "b" "c.txt"
It seems incorrect. I am wondering how to index cc
in file.path()
?
I guess you could call this a list of arguments rather than just a single one. For example, you can access each element of the dots:
f <- function(...) {
list(one = ..1,
three = ..3,
four = ..4,
two = ..2)
}
f(1, 2, 3, 4)
# $one
# [1] 1
#
# $three
# [1] 3
#
# $four
# [1] 4
#
# $two
# [1] 2
But what you really want to do is pass each as individual arguments. So in this case, you need to either do that explicitly (lots of typing) or use do.call
which allows you to pass a list of parameters to functions
cc <- c("", "a", "b", "c.txt")
do.call('file.path', as.list(cc))
# [1] "/a/b/c.txt"
file.path
is nice in that it only has two arguments, one of which you don't need to change but if you did you could do
do.call('file.path', c(as.list(cc), fsep = '/xx/'))
# [1] "/xx/a/xx/b/xx/c.txt"
so in this case you need to pass a named list to the function to match each argument
A side note which I have come across, something like
do.call('base::mean', list(1:4))
# Error in do.call("base::mean", list(1:4)) :
# could not find function "base::mean"
won't work if you need to specify a function in a particular package. You either need to do
f <- base:::mean; do.call('f', list(1:4))
# [1] 2.5
or just
do.call(base::mean, list(1:4))
# [1] 2.5
I was about to post the same as rawr's accepted answer/comment (so decided to add a bit more after waiting for him to post an answer and then giving up waiting although I see he now does have an answer):
do.call('file.path', as.list(cc))
Learning to use as.list
and do.call
was one of those lessons I learned several years down the road to my current perpetual intermediate R mastery. The reason that rawr's answer works is that the arguments to file.path
need to come to the args component of the function as a list. The reason that simply wrapping them with list()
, eg file.path(list(cc))
, fails is that the result is a list of length one, whereas the as.list
function creates a list of length-4. The reason using file.path(as.list(cc))
also fails is that the parser still loops over that argument as a single vector.
Sometimes do.call
is the only way to build a function call
when the argument values are going to be supplied to a ...
(dots) component of a function but exist in some other data-object. If passing to a function with named arguments one can use either lists or pairlists:
> dd <- list(from=1, to=2)
> seq(dd)
[1] 1 2
You can use paste
with collapse="/"
instead. So with:
cc <- c("", "a", "b", "c.txt")
You get:
R> paste(cc, collapse="/")
[1] "/a/b/c.txt"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.