Home > Software design >  Combining '...' and 'data' arguments in an R function
Combining '...' and 'data' arguments in an R function

Time:12-13

I have the following function:

fxn1 <- function (var1, ..., data) {
  if (!missing(data)) {
    var1 <- data[[deparse(substitute(var1))]]
  }
  data.frame(var1, ...)
}

Tree_Data <- data.frame(Tree_Number = as.factor(1:12), Diameter = rnorm(12, 10, 2), Height = rnorm(12, 60, 12))

fxn1(Tree_Number, Tree_Data$Diameter, Tree_Data$Height, data = Tree_Data)

This function has been simplified to illustrate my point.

I want to have two input arguments (var1 and ...) that can be provided as either standalone vectors or columns from a data frame. The ... argument can be one or more vectors or columns, as long as they're the same length as the vector provided for the var1 argument.

How can I write this function such that the data argument can supply columns for both the var1 and ... arguments?

Furthermore, I wish to have the output of this function report the column names from the original data frame (Tree_Number, Diameter, and Height). As it stands, the column names being reported by the function are var1, Tree_Data.Diameter, and Tree_Data.Height.

CodePudding user response:

I'm not sure about your purpose, but if you mean to use function fxn1 as fxn1(Tree_Number, Diameter, Height, data = Tree_Data), you may try

fxn1 <- function (var1, ..., data) {
  if (!missing(data)) {
    var1 <- data[[deparse(substitute(var1))]]
  }
  x <- sapply(substitute((...)), deparse)[-1]
  data.frame(var1, data[x])
}

fxn1(Tree_Number, Diameter, Height, data = Tree_Data)

   var1  Diameter   Height
1     1 11.178169 58.33416
2     2 11.338480 45.01997
3     3 12.524902 30.98330
4     4  6.232644 58.07779
5     5 10.611835 54.18964
6     6  7.009949 55.67097
7     7  9.709637 46.79252
8     8 11.454289 65.89518
9     9  5.845062 63.50421
10   10  8.991004 62.18654
11   11 11.981330 55.69941
12   12  8.488162 57.20142

fxn2 <- function (..., data) {
  x <- sapply(substitute((...)), deparse)[-1]
  data.frame(data[x])
}
fxn2(Tree_Number, Diameter, Height, data = Tree_Data)

   Tree_Number  Diameter   Height
1            1 11.178169 58.33416
2            2 11.338480 45.01997
3            3 12.524902 30.98330
4            4  6.232644 58.07779
5            5 10.611835 54.18964
6            6  7.009949 55.67097
7            7  9.709637 46.79252
8            8 11.454289 65.89518
9            9  5.845062 63.50421
10          10  8.991004 62.18654
11          11 11.981330 55.69941
12          12  8.488162 57.20142

Or simply remove [] in if statement will work.

fxn3 <- function (var1, ..., data) {
  if (!missing(data)) {
    var1 <- data[deparse(substitute(var1))]
  }
  x <- sapply(substitute((...)), deparse)[-1]
  data.frame(var1, data[x])
}

CodePudding user response:

fxn1 <- function (var1, ..., data) {
  nms <- as.character(substitute(...()))
  nm1 <- deparse(substitute(var1))
  if (missing(data))
    setNames(data.frame(c(list(var1), list(...))), 
             sub('.*\\$', '', c(nm1, nms)))
  else data[c(nm1, nms)]
}

Tree_Data <- data.frame(Tree_Number = as.factor(1:12), 
                        Diameter = rnorm(12, 10, 2), Height = rnorm(12, 60, 12))



fxn1(Tree_Data$Tree_Number, Tree_Data$Diameter, Tree_Data$Height)

   Tree_Number  Diameter   Height
1            1 12.692108 73.77180
2            2  9.278630 48.24943
3            3  7.436189 43.20851
4            4  8.961796 64.04443
5            5 12.191659 48.76907
6            6 10.938422 46.87867
7            7 13.732354 66.54974
8            8  9.245929 47.98816
9            9  5.443331 78.79621
10          10  9.633676 69.40670
11          11  9.466689 57.41067
12          12  9.221958 87.18004

fxn1(Tree_Number, Diameter, Height, data = Tree_Data)

   Tree_Number  Diameter   Height
1            1 12.692108 73.77180
2            2  9.278630 48.24943
3            3  7.436189 43.20851
4            4  8.961796 64.04443
5            5 12.191659 48.76907
6            6 10.938422 46.87867
7            7 13.732354 66.54974
8            8  9.245929 47.98816
9            9  5.443331 78.79621
10          10  9.633676 69.40670
11          11  9.466689 57.41067
12          12  9.221958 87.18004
  •  Tags:  
  • r
  • Related