0

I had a function with a signature like this:

myFunction=function(class="Class",v1='y',v2='y',dfparam=df){

where df is a dataframe and it is assumed that there is an attribute called Class in df. I wanted to make it more general so that it can accept a variety of dataframes, df, not just one that has an attribute called Class. So I added in a className parameter and classValue parameter to replace the class parameter. Also, I want to allow unlimited arguments v1, v2, v3 etc. and so I am using the elipsis like this:

myFunctionGeneral = function(className="Class", classValue="democrat", dfparam=df, ...){
  arguments <- list(...)

Prior to using the elipsis, I had a line that used the arguments as follows:

X_bool=dfparam$V1==v1 & dfparam$V2==v2 

I started out doing this:

X_bool=dfparam[,2]==arguments[1] & dfparam[,3]==arguments[2]

but I want to do this for an unlimited number of possible paremeters in the elipsis. So I need to expand this statement by somehow unraveling the ellipsis. Here is an example:

install.packages("vcd")
library(vcd)
data(Arthritis)
AAr=Arthritis[,-c(1,4)]


myFunctionGeneral=function(className="Class",classValue="democrat",dfparam=df, ...){

  dfparam$names<-rownames(dfparam)
  arguments<-list(...)


  dfparamDroppedClass=dfparam[,-1]
  #X_bool=dfparam[,2]==arguments[1] & dfparam[,3]==arguments[2] 
  X_bool=do.call(all, Map("==", dfparamDroppedClass, arguments))


  X=dfparam[X_bool,]


}
matt
  • 131
  • 1
  • 8

1 Answers1

0

This should illustrate the principle:

arguments <- list(1, 2, 3)
params <- list(1, 2, 3)
do.call(all, Map("==", arguments, params))
#[1] TRUE

params <- list(1, 2, 4)
do.call(all, Map("==", arguments, params))
#[1] FALSE

All is equivalent to an arbitrary number of &, and Map iterates == over the two lists.

Edit: Apparently your data.frame has more than one observation. Then you can't use all, but need to use Reduce as in Reduce("&", Map("==", arguments, params)). With your example:

myFunctionGeneral=function(className="Class",classValue="democrat",dfparam=df, ...){

  dfparam$names<-rownames(dfparam)
  arguments<-list(...)

  dfparamDroppedClass=dfparam[, -c(1, 4)]
  #X_bool=dfparam[,2]==arguments[1] & dfparam[,3]==arguments[2] 
  X_bool=Reduce("&", Map("==", dfparamDroppedClass, arguments))

  dfparam[X_bool,]      
}

myFunctionGeneral('Treatment','Placebo',AAr,'Male','Marked')
#   Treatment  Sex Improved names
#4    Treated Male   Marked     4
#5    Treated Male   Marked     5
#6    Treated Male   Marked     6
#8    Treated Male   Marked     8
#14   Treated Male   Marked    14
#52   Placebo Male   Marked    52
Roland
  • 127,288
  • 10
  • 191
  • 288
  • Thank you. I think arguments<-list(...) is analogous to your arguments <- list(1, 2, 3), but I also need a list that contains dfparam[,2], dfparam[,3] and so on but it also has to be of the same size as arguments dynamically and has to begin with 2 not 1. Do you have an idea for this? – matt Aug 18 '17 at 11:54
  • A data.frame is also a list. And you know how to remove the first column of a data.frame, don't you? – Roland Aug 18 '17 at 12:11
  • Thanks! I tried this: dfparamDroppedClass=dfparam[,-1] and then this: X_bool=do.call(all, Map("==", dfparamDroppedClass, arguments)). But I get a warning Warning message: In mapply(FUN = f, ..., SIMPLIFY = FALSE) : longer argument not a multiple of length of shorter. And also the function I am writing does not generate the right output. When I run it with this: X_bool=dfparam[,2]==arguments[1] & dfparam[,3]==arguments[2] , it seems to work. – matt Aug 18 '17 at 12:34
  • Sorry, I won't invest more time without a [minimal reproducible example](https://stackoverflow.com/a/5963610/1412059). – Roland Aug 18 '17 at 12:36
  • I called it with this: myFunctionGeneral('Treatment','Placebo',AAr,'Male','Marked') – matt Aug 18 '17 at 13:00
  • Thanks. I am still getting the same warning when replacing X_bool=dfparam[,2]==arguments[1] & dfparam[,3]==arguments[2] with X_bool=Reduce("&", Map("==", dfparamDroppedClass, arguments)). I will have to study your suggestion. – matt Aug 18 '17 at 14:25