0

I learnt that in R you can pass a variable number of parameters to your function with ...

I'm now trying to create a function and loop through ..., for example to create a dataframe.

    create_df <- function(...) {
      for(i in ...){
        ... <- data.frame(...=c(1,2,3,4),column2=c(1,2,3,4))
      }
    }

create_df(hello,world)

I would like to create two dataframes with this code one named hello and the other world. One of the columns should also be named hello and world respectively. Thanks

This is my error:

Error in create_df(hello, there) : '...' used in an incorrect context
moth
  • 1,833
  • 12
  • 29
  • Functions in R are meant to return values. Generally they should not add variables to calling scopes. This violates the principles of functional programming. There are many options to get the names of values in the `...` from here: https://stackoverflow.com/questions/51259346/how-to-get-names-of-dot-dot-dot-arguments-in-r. But it's important to understand the difference when R expects characters vs symbols and which symbols are evaluated and which are not. At the moment this does not seem like a very R-like function which might be why it's hard to get to work. – MrFlick Oct 12 '21 at 07:55

1 Answers1

3

It's generally not a good idea for function to inject variables into their calling environment. It's better to return values from functions and keep related values in a list. In this case you could do this instead

create_df <- function(...) {
  names <- sapply(match.call(expand.dots = FALSE)$..., deparse)
  Map(function(x) {
    setNames(data.frame(a1=c(1,2,3,4),a2=c(1,2,3,4)), c(x, "column2"))
  }, names)
}

create_df(hello,world)
# $hello
#   hello column2
# 1     1       1
# 2     2       2
# 3     3       3
# 4     4       4

# $world
#   world column2
# 1     1       1
# 2     2       2
# 3     3       3
# 4     4       4

This returns a named list which is much easier to work with in R. We use match.call to turn the ... names into strings and then use those strings with functions that expect them like setNames() to change data.frame column names. Map is also a great helper for generating lists. It's often easier to use map style functions rather than bothering with explicit for loops.

MrFlick
  • 195,160
  • 17
  • 277
  • 295