1

I would like to pass the name of a column name as a variable to a function. Specifically, given the following code:

#------------------------------------------
# Create mock data
#------------------------------------------

DF1 = data.frame(colA = as.Date("2015-09-21") + 0:4, B = 1:5, C = 5:1)
DF2 = data.frame(B = 1:5, C = 5:1)

#------------------------------------------
# Sample function call
#------------------------------------------

colname <- "colA"

b_func <- function( my_dt1, my_dt2, my_col ) {    
  return( eval(substitute( cbind( variable = as.Date("2015-09-21") + 0:4, DF2 ), 
    list(variable = as.name(my_col)))) )
}

b_func( DF1, DF2, colname )

I would expect to get the following output:

        colA B C
1 2015-09-21 1 5
2 2015-09-22 2 4
3 2015-09-23 3 3
4 2015-09-24 4 2
5 2015-09-25 5 1

Instead I am getting the following output where instead of "colA" I am getting "variable".

    variable B C
1 2015-09-21 1 5
2 2015-09-22 2 4
3 2015-09-23 3 3
4 2015-09-24 4 2
5 2015-09-25 5 1

Digging further I found that:

colname <- "colA"
substitute( cbind( variable = as.Date("2015-09-21") + 0:4, DF2 ), list(variable = as.name(colname)))
# returns:  cbind(variable = as.Date("2015-09-21") + 0:4, DF2)
# expected: cbind(colA = as.Date("2015-09-21") + 0:4, DF2)

This example is based on the documentation in the R FAQ but I am unable to make it work. A solution and brief explanation would be much appreciated.

Thanks in advance.

Stan
  • 905
  • 9
  • 20

2 Answers2

2

substitute doesn’t substitute argument names, which are not variables.

You can use do.call instead:

b_func <- function (my_dt1, my_dt2, my_col)
    do.call(cbind, setNames(c(list(as.Date("2015-09-21") + 0:4), DF2),
                            c(my_col, colnames(DF2))))

But Richard has a point in his comment: you can simplify this by cbinding first, and assigning names after that:

b_func <- function (my_dt1, my_dt2, my_col)
    setNames(cbind(as.Date("2015-09-21") + 0:4, DF2), c(my_col, colnames(DF2)))
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
1

I'm confused in that two arguments to your function, my_dt1 and my_dt2, do not seem to be used. All you seem to be doing is adding a column to DF2? If so, just do this:

b_func = function(my_dt, my_col) {
  my_dt[[my_col]] = as.Date("2015-09-21") + 0:4
  my_dt
}
bramtayl
  • 4,004
  • 2
  • 11
  • 18