christiaan pauw
2012-Aug-07 08:52 UTC
[R] Passing arguments to a function within a function ...
Hallo Everybody How do you specify arguments for a function used within another function? Here is my problem: I am reconstructing a calculator for the burden of disease due to air pollution from publications and tools published by the WHO. The calculations make use of published dose-response relationships for particular health end-points. This is then applied to populations with known or estimated levels of exposure and incidence rates to calcute the number of cases of each end-point attributable to each pollutant. I have functions that work on their own but when is have to use the one within the other, I don't know how to specify its arguments Here are example data and the functions: ######################################################## ## Example data frame with population, concentration and cases ## x = data.frame(Name = LETTERS[1:10], pop=sample(x=1000:10000,size=10), Xbabies = 0.106, Xkids = 0.232, Xteens = 0.375, Xadults = 0.235, Xaged = 0.52, cases = sample(x=100:500,size=10), conc = sample(x=20:125,size=10) ) ## Two of the published dose-response relationships adult.CP.mortality = list(end.point = "Cardiopulmanory mortality in adults over 30", pollutant = "PM10", relationship = "log-linear", beta = c(0.0562,0.1551,0.2541), Xpop c("Xbabies","Xkids","Xteens","Xadults","Xaged")[4:5]) adult.LC.mortality = list(end.point = "Lung Cancer mortality in adults over 30", pollutant = "PM10", relationship = "log-linear", beta = c(0.0856, 0.2322,0.3787), Xpop c("Xbabies","Xkids","Xteens","Xadults","Xaged")[4:5]) ## Generic function to calculculate the Attributable cases for a pollutant in a population dose.response <- function(pop, Xpop = 1, conc, base.conc=7.5, relationship = c("linear","log-linear")[1], beta=c(0.0006,0.0008,0.0010), cases=NULL, incidence.rate=NULL, par = c("low estimate","cental estimate","high estimate"), verbose = FALSE ){ # Turn case rate into case number d <- cases if(verbose==TRUE) message("d = ", d) if(verbose==TRUE) message("pop = ", pop) if(verbose==TRUE) message("beta = ", beta) if(verbose==TRUE) message("conc = ", conc) if(verbose==TRUE) message("base.coc = ", base.conc) if(verbose==TRUE) message("relationship = ", relationship) if(is.null(cases)==TRUE) {d <- incidence.rate*pop} # use incidence rate if cases are not available if(relationship == "linear") {RR = exp(beta*(conc-base.conc))} #RR=exp[beta(X-Xo)] if(relationship == "log-linear") {RR = ((conc+1)/(base.conc+1))^beta} if(verbose==TRUE) message("RR = ", RR) AF = (RR-1)/RR #AF=(RR-1)/RR if(verbose==TRUE) message("AF = ", AF) AM = AF * d #AM = AF * cases if(verbose==TRUE) message("AM = ", AM) out = data.frame(beta=beta,cases=d, RelativeRisk=RR,AttributableFraction=AF, AttributableInsidence=AM) rownames(out) = c("low estimate","cental estimate","high estimate") if(verbose==TRUE) message("dimentions of out = ", dim(out)) out.idx = na.omit(match(par,rownames(out))) out[out.idx,] } ## Function using the published dose-response relationships with the generic function drep <- function(pop.conc=x,sicklist=adult.CP.mortality,...){ dr.out=by(x,x$Name,function(x){z=as.data.frame((x)) dose.response(pop=z$pop*sum(z[,adult.CP.mortality$Xpop]), conc=z$conc, cases=z$cases, relationship sicklist$relationship, beta = sicklist$beta, Xpop = sicklist$Xpop, par = c("low estimate","cental estimate","high estimate")[2] , verbose=FALSE ) } ) names(dr.out) <- paste(sicklist$end.point,": ", names(dr.out),sep="") dr.out } ##################################################### This is where the trouble starts: What do I do if I need to pass the argument base.conc=10 or a different option for par= to dose.response() ? At the moment it works becuase it uses the default, which will not be valid in all cases. Thanks in advance Christiaan -- Christiaan Pauw Nova Institute www.nova.org.za
Rui Barradas
2012-Aug-07 09:34 UTC
[R] Passing arguments to a function within a function ...
Hello, Your problem seems simple, if I understand it correctly. Just add an extra argument to the caller function, drep(). drep <- function(pop.conc = x, sicklist = adult.CP.mortality, par = "cental estimate", ...) { #--------> This extra argument dr.out = by(x, x$Name, function(x) { z = as.data.frame((x)) dose.response(pop = z$pop * sum(z[, adult.CP.mortality$Xpop]), conc = z$conc, cases = z$cases, relationship = sicklist$relationship, beta = sicklist$beta, Xpop = sicklist$Xpop, par = par, #----------------> Note the difference (!) verbose = FALSE) }) names(dr.out) <- paste(sicklist$end.point, ": ", names(dr.out), sep = "") dr.out } In this case, the new argument has a default value.When the callee dose.response() is called, the first 'par' is the name one of it's arguments, the second 'par' is a value, the passed to value. The first is a name, it does not have a value and can not, for instance, be printed, only the second can. They are completely different in nature. And the same for other arguments, like 'base.conc'. Hope this helps, Rui Barradas Em 07-08-2012 09:52, christiaan pauw escreveu:> Hallo Everybody > > How do you specify arguments for a function used within another function? > > Here is my problem: > > I am reconstructing a calculator for the burden of disease due to air > pollution from publications and tools published by the WHO. The > calculations make use of published dose-response relationships for > particular health end-points. This is then applied to populations with > known or estimated levels of exposure and incidence rates to calcute > the number of cases of each end-point attributable to each pollutant. > I have functions that work on their own but when is have to use the > one within the other, I don't know how to specify its arguments > > Here are example data and the functions: > > ######################################################## > ## Example data frame with population, concentration and cases ## > > x = data.frame(Name = LETTERS[1:10], > pop=sample(x=1000:10000,size=10), > Xbabies = 0.106, > Xkids = 0.232, > Xteens = 0.375, > Xadults = 0.235, > Xaged = 0.52, > cases = sample(x=100:500,size=10), > conc = sample(x=20:125,size=10) > ) > > ## Two of the published dose-response relationships > > adult.CP.mortality = list(end.point = "Cardiopulmanory mortality in > adults over 30", > pollutant = "PM10", > relationship = "log-linear", > beta = c(0.0562,0.1551,0.2541), > Xpop > c("Xbabies","Xkids","Xteens","Xadults","Xaged")[4:5]) > > adult.LC.mortality = list(end.point = "Lung Cancer mortality in adults over 30", > pollutant = "PM10", > relationship = "log-linear", > beta = c(0.0856, 0.2322,0.3787), > Xpop > c("Xbabies","Xkids","Xteens","Xadults","Xaged")[4:5]) > > ## Generic function to calculculate the Attributable cases for a > pollutant in a population > dose.response <- function(pop, > Xpop = 1, > conc, > base.conc=7.5, > relationship = c("linear","log-linear")[1], > beta=c(0.0006,0.0008,0.0010), > cases=NULL, > incidence.rate=NULL, > par = c("low estimate","cental > estimate","high estimate"), > verbose = FALSE > ){ > # Turn case rate into case number > d <- cases > if(verbose==TRUE) message("d = ", d) > if(verbose==TRUE) message("pop = ", pop) > if(verbose==TRUE) message("beta = ", beta) > if(verbose==TRUE) message("conc = ", conc) > if(verbose==TRUE) message("base.coc = ", base.conc) > if(verbose==TRUE) message("relationship = ", relationship) > if(is.null(cases)==TRUE) {d <- incidence.rate*pop} # use incidence > rate if cases are not available > if(relationship == "linear") {RR = exp(beta*(conc-base.conc))} > #RR=exp[beta(X-Xo)] > if(relationship == "log-linear") {RR = ((conc+1)/(base.conc+1))^beta} > if(verbose==TRUE) message("RR = ", RR) > AF = (RR-1)/RR #AF=(RR-1)/RR > if(verbose==TRUE) message("AF = ", AF) > AM = AF * d #AM = AF * cases > if(verbose==TRUE) message("AM = ", AM) > out = data.frame(beta=beta,cases=d, > RelativeRisk=RR,AttributableFraction=AF, > AttributableInsidence=AM) > rownames(out) = c("low estimate","cental estimate","high estimate") > if(verbose==TRUE) message("dimentions of out = ", dim(out)) > out.idx = na.omit(match(par,rownames(out))) > out[out.idx,] > } > > ## Function using the published dose-response relationships with the > generic function > drep <- function(pop.conc=x,sicklist=adult.CP.mortality,...){ > dr.out=by(x,x$Name,function(x){z=as.data.frame((x)) > > dose.response(pop=z$pop*sum(z[,adult.CP.mortality$Xpop]), > conc=z$conc, > cases=z$cases, > relationship > sicklist$relationship, > beta = sicklist$beta, > Xpop = sicklist$Xpop, > par = c("low > estimate","cental estimate","high estimate")[2] > , verbose=FALSE > ) > } ) > names(dr.out) <- paste(sicklist$end.point,": ", names(dr.out),sep="") > dr.out > } > > ##################################################### > > This is where the trouble starts: What do I do if I need to pass the > argument base.conc=10 or a different option for par= to > dose.response() ? At the moment it works becuase it uses the default, > which will not be valid in all cases. > > Thanks in advance > Christiaan > > > -- > Christiaan Pauw > Nova Institute > www.nova.org.za > > ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
christiaan pauw
2012-Aug-07 10:36 UTC
[R] Passing arguments to a function within a function ...
Thanks Rui It works. On 7 August 2012 11:34, Rui Barradas <ruipbarradas at sapo.pt> wrote:> Hello, > > Your problem seems simple, if I understand it correctly. Just add an extra > argument to the caller function, drep().Christiaan Pauw Nova Institute www.nova.org.za