简体   繁体   中英

How to use arguments in a function call as names in dataframes in R?

I am trying to modify the output of tapply to obtain a vertical transposition of the results.

Something like this:

Levels of y  Mean of x

A              1.7

B              3.5

C              5.0

instead of:

A     B    C

1.7  3.5  5.0 

I have managed to produce a dataframe, by:

myfunction=function(x,y,FUN,...) {
array1<-tapply(x,y,FUN,...)
a<-data.frame(names(array1),array1)
rownames(a)<-NULL
print(a)
}

attach(InsectSprays)

myfunction(count,spray,mean)

This works and produces this:

  names.array1.    array1
1             A 14.500000
2             B 15.333333
3             C  2.083333
4             D  4.916667
5             E  3.500000
6             F 16.666667

Problem 1)

Now I would like to modify the function in order to change colnames of the dataframe using the arguments which are passed to myfunction at the call of the function itself (in this specific case "spray" and "Sum of count").

I have tried something like this

myfunction=function(x,y,FUN,...) {
array1<-tapply(x,y,FUN,...)
a<-data.frame(names(array1),array1)
rownames(a)<-NULL
colnames(a)<-c(y,print(FUN,"of",x)
print(a)
}

but I think R tries to use the entire vector y instead of its name.

I can not figure out what the solution maybe.

I have also tried with args() and formals() without luck.

Problem 2)

I would like to call myfunction in this way, passing data=... to tapply from the original call (to avoid attaching and detaching the dataset or passing variables in the form df$variable1). I have tried:

myfunction=function(x,y,FUN,...) {
array1<-tapply(x,y,FUN,...)
a<-data.frame(names(array1),array1)
rownames(a)<-NULL
print(a)
}

myfunction<-(count,spray,sum,data=InsectSprays)

but tapply does not find the object "spray".

Obviously the solution to all my problems may have been using aggregate(), but I think the solutions to these questions will teach me a lot about writing functions. Thank you very much for your help.

The method you are trying to employ is called non-standard evaluation , and it is used extensively in the tidyverse family of packages, as well as some of the functions in base R such as with , within and the $ operator.

You might wish to explore the concept here .

In the meantime, it is also possible to use a function in base R that employs non-standard evaluation using deparse and substitute :

myfunction <- function(x, y, data, FUN, ...) 
{
  x <- deparse(substitute(x))
  y <- deparse(substitute(y))
  array1 <- tapply(data[[x]], data[[y]], FUN, ...)
  a <- setNames(data.frame(names(array1),array1), 
               c(y, paste(deparse(substitute(FUN)), "of", y)))
  rownames(a) <- NULL
  print(a)
}

myfunction(count, spray, data = InsectSprays, mean)
#>   spray mean of spray
#> 1     A     14.500000
#> 2     B     15.333333
#> 3     C      2.083333
#> 4     D      4.916667
#> 5     E      3.500000
#> 6     F     16.666667

myfunction(cyl, gear, mtcars, sum)
#>   gear sum of gear
#> 1    3         112
#> 2    4          56
#> 3    5          30

A more advanced version of this function would also allow you to pass vectors directly without a data argument:

myfunction <- function(x, y, data, FUN, ...) 
{
  if (missing(data)) data <- parent.frame()
  y_name   <- deparse(substitute(y))
  col_name <- paste(deparse(substitute(FUN)), "of", y_name)
  x        <- eval(substitute(x), envir = as.environment(data))
  y        <- eval(substitute(y), envir = as.environment(data))

  array1 <- tapply(x, y, FUN, ...)
  a      <- setNames(data.frame(names(array1), array1), c(y_name, col_name))
  rownames(a) <- NULL
  print(a)
}

This has the same functionalty as the first example, but in addition you can run it using vectors in the calling environment:

var1 <- 1:10
var2 <- rep(1:2, 5)

myfunction(var1, var2, FUN = median)
#>   var2 median of var2
#> 1    1              5
#> 2    2              6

Created on 2020-05-27 by the reprex package (v0.3.0)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM