Skip to content

multiple versions of function

8 messages · ivo welch, David Winsemius, R. Michael Weylandt +1 more

#
dear R experts:

I want to define a function the calculates the black-scholes value.
it takes 5 named parameters, BS <- function(S,K,dt,rf,sigma) {} .
let's presume I want to be able to call this not only with my 5
numeric vectors BS( sigma=0.3, S=100, K=100, dt=1, rf=0.1 ) and BS(
100, 100, 1, 0.1, 0.3), but also with a data frame that contains the
variables alll in a neat data frame already, BS( data.frame( S=100,
K=100, dt=1, rf=0.1, sigma=0.3 )).  I could of course define BS6 and
BS1, but it would be nice to wrap this functionality into one function
that can do both.

I know that BS has to parse an '...' argument, but there could be a
couple of magical R functions that might make this easier than I would
do it with my planned clunky version.     what's the elegant version?

/iaw


----
Ivo Welch (ivo.welch at gmail.com)
#
On Jan 7, 2013, at 3:57 PM, ivo welch wrote:

            
apply( dfrm, 1, BS)
#
hi david---can you give just a little more of an example?  the
function should work with call by order, call by name, and data frame
whose columns are the names.  /iaw


----
Ivo Welch (ivo.welch at gmail.com)
On Mon, Jan 7, 2013 at 4:25 PM, David Winsemius <dwinsemius at comcast.net> wrote:
#
On Jan 7, 2013, at 6:58 PM, ivo welch wrote:

            
It is I who should be expecting you to provide an example.

--  
David.
David Winsemius, MD
Alameda, CA, USA
1 day later
#
mea culpa.

f <- function(...) {
  ## parse out the arguments and then do something with them
}

## all of these should result in the same actions
f(2,3)  ## interprets a to be first and b to be second
f(a=2,b=3)
f(b=3,a=2)
f(data.frame(a=2,b=3))
f(data.frame(b=3,a=1))
On Tue, Jan 8, 2013 at 8:00 AM, David Winsemius <dwinsemius at comcast.net> wrote:
#
On Jan 9, 2013, at 1:00 PM, ivo welch wrote:

            
In the last two instances you are only passing a single object. I suppose you could construct the argument list with

f <- function( a=NA, ...) { code}

But this works:

 f <- function(a=NA, b=NA) if( !is.list(a) ) {print(a); cat("\n"); print(b) } else{
                                          with(a, {print(a); cat("\n"); print(b)} ) }

There is some concern for using with in functions so maybe you would want access values with 

   a[["a"]] and a[["b"]]

Test output.
[1] 2

[1] 3
[1] 2

[1] 3
[1] 2

[1] 3
[1] 2

[1] 3
[1] 1

[1] 3
David Winsemius
Alameda, CA, USA
#
On Jan 9, 2013, at 9:00 PM, ivo welch <ivo.welch at gmail.com> wrote:

            
These will all be the same automatically for functions with the signature f(a, b, ...) [grammatical not variadic ellipsis there] -- basic call matching, nothing fancy.
Perhaps test if your first arg is a df and, if so, loop over it row-wise building the function calls with do.call() -- something like: 

# Untested
f <- function(a, b){
    if(is.data.frame(a)) return(lapply(seq_len(NROW(a)), function(n) do.call(f, a[n,]))
    ## regular function code here
}

You should probably also fiddle with Recall() to make the recursive structure a little more robust. 

Though it seems that generic functions make more sense here.

Michael Weylandt
#
You could make your 'f' a generic function and define methods
for various types.  E.g., using S3 generics, define
   f <- function(a, b) UseMethod("f")
   f.default <- function(a, b) 10 * a + b
   f.data.frame <- function(df) f(df$a, df$b)
and use them as
  > f(b=5:7, a=1:3)
  [1] 15 26 37
  > f(1:3, 5:7)
  [1] 15 26 37
  > d <- data.frame(b=5:7, a=1:3)
  > f(d)
  [1] 15 26 37

Bill Dunlap
Spotfire, TIBCO Software
wdunlap tibco.com