s-news
[Top] [All Lists]

Summary: Using apply for functions with more than one argument

To: <S-News <s-news@wubios.wustl.edu>
Subject: Summary: Using apply for functions with more than one argument
From: "Luis Apiolaza" <luis.apiolaza@forestrytas.com.au>
Date: Wed, 08 Jun 2005 08:51:26 +1000
Thanks a lot to all people that reply to the list and personally: Mark
Leeds, Jo Jiao, Martin Studer, Christopher Green, Frank Harrell, Xao
Ping, Richard Heiberger, Sarah Goslee, Gerald Jean, Greg Johnson and
Rich from Mango.

Most solutions are variations of the same theme: change the function
definition, so it receives an array as an argument and then access the
elements of the array inside the function, either using names or the
position number of the array. Using Martin's code :

# Defining the data to use as test
my.a <- array(data = c(15, 10, 9, 11, 7.5, 10.5, 8.25, 9, 7.6, 10.7,
1.5,
1.0, 0.8, 1.3, 2.7, 1.0, 1.9, 1.4, 0.9, 1.55), dim = c(10, 2), dimnames
= list(NULL, c("Height", "Diameter")))

# A funny looking fake volume function
stem.volume <- function(datarow)
{
        return(datarow["Height"]^2 / datarow["Diameter"])
}

# Using apply by rows (1), so it passes an array to the function
res <- apply(my.a, 1, stem.volume)

It is also possible to pass additional arguments to the functions (like
a constant) just appending them to the call, like:

res <- apply(my.a, 1, stem.volume, const = 3, z = 5)

Gerald Jean, pointed out something that I discovered when first
implementing the code sent by Martin: apply is slow, and in fact did not
perform very differently from a for() loop calling the function.

Other alternative codings:

- Frank Harrell suggests having a look at the mApply function in the
Hmisc package.

- Christopher Green offers this call:

apply(my.a, 1, function(x) stem.volume(x[1],x[2])), which would work
without the need for redefining the stem.volume function.

- Rich from Mango (yummy!) Solutions offers this alternative:

  myMat <- matrix(rpois(20, 3), ncol=2)    # Create some data
  myFun <- function(x, y) x + y                # Create a function
taking 2 numbers
  apply(myMat, 1, function(x) do.call("myFun", as.list(x))) # Make the
call

- Richard Heiberger does something like:
# Tiny dataset
 tmp <- cbind(h=10:13, d=5:6)
apply(tmp, 1, function(x) {x["h"] * x["d"]^2 * pi/4})
or
sapply(1:nrow(tmp), function(i, h, d) {h[i] * d[i]^2 * pi/4},
h=tmp[,"h"], d=tmp[,"d"])

Thanks again,


Luis


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dr Luis A. Apiolaza
Principal Forest Biometrician
Forestry Tasmania
GPO Box 207
Hobart Tas 7001
Australia

email:    Luis.Apiolaza@forestrytas.com.au
phone: +61-3-6233 8127
web:     http://www.forestrytas.com.au
             http://uncronopio.org
"All I want is a warm bed, a kind word,
 and unlimited power" --Ashleigh Brilliant
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-----------------------------------------------------
This transmission is intended solely for the person or 
organisation to whom it is addressed.
It is confidential and may contain legally privileged 
information. If you have received this transmission in 
error,you may not use, copy or distribute it.
Please advise us by return e-mail or by phoning 61 3 62338203 
and immediately delete the transmission in its entirety.
We will meet your reasonable expenses of notifying us.
Despite our use of anti-virus software, Forestry Tasmania 
cannot guarantee that this transmission is virus-free. 
-----------------------------------------------------

<Prev in Thread] Current Thread [Next in Thread>
  • Summary: Using apply for functions with more than one argument, Luis Apiolaza <=