? Tue, 11 Jun 2024 18:44:08 +0000 "Levine, Michael" <mlevins at purdue.edu> ?????:> Let us say we have a function > > F <- function(x){ body of the function} > > Where x is, in general, a d by 1 vector with d>1. Now I want to > integrate out some of the coordinates of x, e.g. x[1] or x[2] or both > of them etc. I'm well aware of how to integrate out e.g. y if a > function is defined as f <- function (x,y) {body of the function} > where y is a scalar.The reason integrate() wants a separate function argument for the integration coordinate is so that it could give the function a vector of different values of the variable and receive a vector of the same length containing the corresponding values of the function. If the problem is small enough to make performance considerations irrelevant, you can use Vectorize to make a function compatible with integrate() from your function F: x <- x0 z <- z0 Fiy <- Vectorize(function(y) F(c(x, y, z))) integrate(Fiy, ymin, ymax) The resulting function Fiy will accept a vector of values for y and translate it into multiple calls to F with a three-element vector argument as it expects. Achieving better performance will require rewriting the function F to be "vectorised", i.e. to accept vectors for arguments and return a vector of the same length. -- Best regards, Ivan
Dear Ivan, Thank you very much for your suggestions. I understand what you are saying. I am afraid I didn't explain well enough what was needed, however. Let us again restrict ourselves to the case of two dimensions. Then, what I have is a bivariate density function f(x,y) and my intention is to obtain f(x) by integrating out y. However, I don't only need to know the value of the marginal density f(x) at one point - I need to integrate it again to obtain the marginal cumulative density function F(x) as a next step. Thus, I also need to pass x as an additional parameter before integration, and this is what makes the problem more difficult. I tried to do the following (here H and j are additional arguments needed to obtain the estimated bivariate density function): f.int1 <- function(x,y) {Vectorize (function(y) f(c(x,y),H=H,j=j))} mrg.d1 <- function(x){ integrate(f.int1,lower=-3,upper=3)$value } mrg.cdf1 <- function(x){ integrate(mrg.d1,lower=-Inf,upper=x)$value } I received the following error message: Error in integrate(f.int1, lower = -3, upper = 3) : evaluation of function gave a result of wrong length How would you go about performing this task? Yours sincerely, Michael Michael Levine Associate Professor, Statistics Department of Statistics Purdue University 250 North University Street West Lafayette, IN 47907 USA email: mlevins at purdue.edu Phone: +1-765-496-7571 Fax: +1-765-494-0558 URL: www.stat.purdue.edu/~mlevins ________________________________ From: Ivan Krylov <ikrylov at disroot.org> Sent: Wednesday, June 12, 2024 6:41 AM To: Levine, Michael <mlevins at purdue.edu> Cc: r-help at r-project.org <r-help at r-project.org> Subject: Re: [R] Integration of functions with a vector argument [You don't often get email from ikrylov at disroot.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] ---- External Email: Use caution with attachments, links, or sharing data ---- ? Tue, 11 Jun 2024 18:44:08 +0000 "Levine, Michael" <mlevins at purdue.edu> ?????:> Let us say we have a function > > F <- function(x){ body of the function} > > Where x is, in general, a d by 1 vector with d>1. Now I want to > integrate out some of the coordinates of x, e.g. x[1] or x[2] or both > of them etc. I'm well aware of how to integrate out e.g. y if a > function is defined as f <- function (x,y) {body of the function} > where y is a scalar.The reason integrate() wants a separate function argument for the integration coordinate is so that it could give the function a vector of different values of the variable and receive a vector of the same length containing the corresponding values of the function. If the problem is small enough to make performance considerations irrelevant, you can use Vectorize to make a function compatible with integrate() from your function F: x <- x0 z <- z0 Fiy <- Vectorize(function(y) F(c(x, y, z))) integrate(Fiy, ymin, ymax) The resulting function Fiy will accept a vector of values for y and translate it into multiple calls to F with a three-element vector argument as it expects. Achieving better performance will require rewriting the function F to be "vectorised", i.e. to accept vectors for arguments and return a vector of the same length. -- Best regards, Ivan [[alternative HTML version deleted]]
? Wed, 12 Jun 2024 23:42:18 +0000 "Levine, Michael" <mlevins at purdue.edu> ?????:> f.int1 <- function(x,y) {Vectorize (function(y) f(c(x,y),H=H,j=j))}Vectorize returns a callable function(y), so wrapping it in a function(x,y) will not work. Since you'd like to integrate over y, we can perform the same transformation manually using vapply: # A version of f(...) that can be integrated over y f.int1 <- function(y, x, H, j) vapply(y, function(y) f(c(x,y), H = H, j = j), numeric(1)) The same transformation can be performed using Vectorize as follows: f.int1 <- Vectorize( function(y, x, H, j) f(c(x,y), H = H, j = j), vectorize.args = 'y' )> mrg.d1 <- function(x){ > integrate(f.int1,lower=-3,upper=3)$value > }We can then integrate f.int1 over y, making sure to pass the remaining scalar parameters to the function: # mrg.d1(x, H, j) = ? f(y,x,H,j) dy from -3 to 3 mrg.d1 <- function(x, H, j) integrate(f.int1, lower=-3, upper=3, x = x, H = H, j = j)$value> mrg.cdf1 <- function(x){ > integrate(mrg.d1,lower=-Inf,upper=x)$value > }Unfortunately, mrg.d1 is once again not vectorised and may give wrong answers or raise exceptions with non-scalar x. We can now perform the same transformation so that the function would work with integrate(): # Version of mrg.d1 integratable over x mrg.d1.int <- function(x, H, j) vapply(x, mrg.d1, numeric(1), H = H, j = j) Here, instead of having to combine arguments like in f.int1, we can just use vapply() to call the original mrg.d1 for every scalar element inside the vector x given to mrg.d1.int. Alternatively, mrg.d1.int <- Vectorize(mrg.d1, 'x') A vectorised function can then be integrated: # mrg.cdf1(x, H, j) = ? mrg.d1(x', H, j) dx' from -? to x mrg.cdf1 <- function(x, H, j) integrate(mrg.d1.int, lower=-Inf, upper=x, H = H, j = j)$value This double nested loop (produced by Vectorize() and mapply() or manually with vapply()) may be not very fast. If you rewrite your function f to accept matrices containing values of (x, y) for many evaluations of the function and to return vectors of the resulting values, you'll be able to use the CRAN package 'cubature' <https://CRAN.R-project.org/package=cubature> to integrate it over multiple variables at once. -- Best regards, Ivan