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()
?
Use the which() Function to Find the Index of an Element in R. The which() function returns a vector with the index (or indexes) of the element which matches the logical vector (in this case == ).
To list all files in a directory in R programming language we use list. files(). This function produces a list containing the names of files in the named directory. It returns a character vector containing the names of the files in the specified directories.
Character/string – each element in the vector is a string of one or more characters. Built in character vectors are letters and LETTERS which provide the 26 lower (and upper) case letters, respecitively. > y = c("a", "bc", "def") > length(y)
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()
, e.g 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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With