How to use R's ellipsis feature when writing your own function?
I read answers and comments and I see that few things weren't mentioned:
data.frame
useslist(...)
version. Fragment of the code:object <- as.list(substitute(list(...)))[-1L]
mrn <- is.null(row.names)
x <- list(...)object
is used to do some magic with column names, butx
is used to create finaldata.frame
.
For use of unevaluated...
argument look atwrite.csv
code wherematch.call
is used.As you write in comment result in Dirk answer is not a list of lists. Is a list of length 4, which elements are
language
type. First object is asymbol
-list
, second is expression1:10
and so on. That explain why[-1L]
is needed: it removes expectedsymbol
from provided arguments in...
(cause it is always a list).
As Dirk statessubstitute
returns "parse tree the unevaluated expression".
When you callmy_ellipsis_function(a=1:10,b=11:20,c=21:30)
then...
"creates" a list of arguments:list(a=1:10,b=11:20,c=21:30)
andsubstitute
make it a list of four elements:List of 4
$ : symbol list
$ a: language 1:10
$ b: language 11:20
$ c: language 21:30First element doesn't have a name and this is
[[1]]
in Dirk answer. I achieve this results using:my_ellipsis_function <- function(...) {
input_list <- as.list(substitute(list(...)))
str(input_list)
NULL
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)As above we can use
str
to check what objects are in a function.my_ellipsis_function <- function(...) {
input_list <- list(...)
output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
return(output_list)
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
int [1:10] 1 2 3 4 5 6 7 8 9 10
int [1:10] 11 12 13 14 15 16 17 18 19 20
int [1:10] 21 22 23 24 25 26 27 28 29 30
$a
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.00 3.25 5.50 5.50 7.75 10.00
$b
Min. 1st Qu. Median Mean 3rd Qu. Max.
11.0 13.2 15.5 15.5 17.8 20.0
$c
Min. 1st Qu. Median Mean 3rd Qu. Max.
21.0 23.2 25.5 25.5 27.8 30.0It's ok. Lets see
substitute
version:my_ellipsis_function <- function(...) {
input_list <- as.list(substitute(list(...)))
output_list <- lapply(X=input_list, function(x) {str(x);summary(x)})
return(output_list)
}
my_ellipsis_function(a=1:10,b=11:20,c=21:30)
symbol list
language 1:10
language 11:20
language 21:30
[[1]]
Length Class Mode
1 name name
$a
Length Class Mode
3 call call
$b
Length Class Mode
3 call call
$c
Length Class Mode
3 call callIsn't what we needed. You will need additional tricks to deal with these kind of objects (as in
write.csv
).
If you want use ...
then you should use it as in Shane answer, by list(...)
.
What does passing an ellipsis (...) as an argument mean in R?
The typical use of ...
argument is when a function say f
internally calls a function g
and uses ...
to pass arguments to g
without explicitly listing all those arguments as its own formal arguments. One may want to do this, for example, when g
has a lot of optional arguments that may or may not be needed by the user in the function f. Then instead of adding all those optional arguments to f
and increasing complexity, one may simply use ...
.
What it means, as you asked, is the function f
will simply ignore these and pass them on to g
. The interesting thing is that ...
may even have arguments that g
does not want and it will ignore them too, for say h
if it needed to use ...
too. But also see this so post for a detailed discussion.
For example consider:
f <- function (x, y, ...) {
# do something with x
# do something with y
g(...) # g will use what it needs
h(...) # h will use that it needs
# do more stuff and exit
}
Also, see here in the intro-R manual for an example using par
.
Also, this post shows how to unpack the ...
if one was writing a function that made use of it.
How do I save the contents of ellipsis in R to be used in deeply nested function calls?
Change the first line to this:
load.samples <- function(..., path = ".") {
The trick is that ...
should come after the regular parameters, but before the named parameters.
R: Lexical Scoping issue when creating a function with ellipsis argument
You can use quosures from rlang to capture the arguments in ...
then unquote splice them into a select
call:
library(tidyverse)
library(rlang)
qft <- function(data, ...){
args <- enquos(...)
vars <- select(data, !!!args)
ft <- data.frame(table(vars))
ft[ft$Freq != 0, ]
}
qft(mtcars, cyl, gear)
# cyl gear Freq
#1 4 3 1
#2 6 3 2
#3 8 3 12
#4 4 4 8
#5 6 4 4
#7 4 5 2
#8 6 5 1
#9 8 5 2
R: Using ellipsis with a function that takes a arbitrary number of arguments
You don't need to write your own function. You can do this with paste
.
paste(1:3,collapse=",")
# [1] "1,2,3"
How to see if ... ellipses in R contains a certain argument?
We can capture the ...
in a list
and convert the whole elements to a key/value pair. Then, extract the elements based on the name. If we are not passing that particular named element, it will return NULL
. We make use of this behavior of NULL
to concatenate with the default value of 10 in maxRes
and select the first element ([1]
) so that if it is NULL, the default 10 is selected, or else the value passed will be selected. Likewise, do this on all those objects that the OP wanted to override
top_videos <- function(...) {
nm1 <- list(...)
lst1 <- as.list(nm1)
dim <- c(lst1[["dimensions"]], "video")[1]
met <- c(lst1[["metrics"]], "views,averageViewDuration")[1]
maxRes <- c(lst1[['maxResults']], 10)[1]
#temp <- yt_request(dimensions = dim,
metrics = met, maxResults = maxRes, token = myToken)
#temp
maxRes
}
-testing
top_videos(maxResults = 20)
#[1] 20
top_videos(hello = 5)
#[1] 10
Include extra (ellipsis/dot dot dot) arguments within custom function
First of all your example seems to not be a valid one.
For me updated function works correctly.
library(dplyr)
library(tidytext)
library(janeaustenr)
count_tokens <- function(data,output,token="words", ...){
d %>%
select(txt) %>%
tidytext::unnest_tokens(output, input="txt", token = token, ...) %>%
n_distinct()
}
d <- tibble(txt = prideprejudice)
count_tokens(d, "word", to_lower = FALSE)
#> [1] 6915
count_tokens(d, "ngram", token = "ngrams", to_lower = FALSE, n = 8)
#> [1] 122189
count_tokens(d, "ngram", token = "ngrams", to_lower = FALSE, n = 5)
#> [1] 121599
count_tokens(d, "ngram", token = "ngrams", to_lower = FALSE, n = 3)
#> [1] 104664
Created on 2021-02-03 by the reprex package (v0.3.0)
R: using a list for ellipsis arguments
How about
newmean <- function(X, ...){
args <- as.list(substitute(list(...)))[-1L]
z<-list(X)
z<-c(z,args)
do.call(mean,z)
}
Related Topics
How to Subset Matrix to One Column, Maintain Matrix Data Type, Maintain Row/Column Names
Force the Origin to Start At 0
Create a Sequential Number (Counter) For Rows Within Each Group of a Dataframe
General Suggestions For Debugging in R
Explicitly Calling Return in a Function or Not
Make the Background of a Graph Different Colours in Different Regions
Extract a Dplyr Tbl Column as a Vector
How to Count the Number of Unique Values by Group
Select Groups Based on Number of Unique/Distinct Values
How to Delete a Row by Reference in Data.Table
Sum Rows in Data.Frame or Matrix
Create Grouping Variable For Consecutive Sequences and Split Vector
Expert R Users, What's in Your .Rprofile
How to Select the Rows With Maximum Values in Each Group With Dplyr