How to integrate only a variable in multivariate function in R? - r

I have the next function:
f <- function(x,y,z,w) {dpois(x, lambda = w*cos(y-z) ) }
I want to construct a function g(y,z,w) defined by the integral of f with respect to x. I can do it when I have two variables, the code is for example, something like this
margin <- function(y) { sapply(y, function(y) { integrate(function(x) f(x,y), llimx, ulimx)$value }) }
But I don't know how to do that for more than two variables.

Maybe you can try the code below
f <- Vectorize(function(x,y,z,w) dpois(x, w*cos(y-z)),"x")
g <- function(y,z,w) integrate(f, lower = 0, upper =Inf, y, z, w)

Related

Integrating under a curve in R

I apologise if this is a duplicate; I've read answers to similar questions to no avail.
I'm trying to integrate under a curve, given a specific formula (below) for said integration.
As a toy example, here's some data:
Antia_Model <- function(t,y,p1){
r <- p1[1]; k <- p1[2]; p <- p1[3]; o <- p1[4]
P <- y[1]; I <- y[2]
dP = r*P - k*P*I
dI = p*I*(P/(P + o))
list(c(dP,dI))
}
r <- 0.25; k <- 0.01; p <- 1; o <- 1000 # Note that r can range btw 0.1 and 10 in this model
parms <- c(r, k, p, o)
P0 <- 1; I0 <- 1
N0 <- c(P0, I0)
TT <- seq(0.1, 50, 0.1)
results <- lsoda(N0, TT, Antia_Model, parms, verbose = FALSE)
P <- results[,2]; I <- results[,3]
As I understand it, I should be able to use the auc() function from the MESS package (can I just use the integrate() function? Unclear...), which should look something like this:
auc(P, TT, from = x1, to = x2, type = "spline")
Though I don't really understand how to use the "from" and "to" arguments, or how to incorporate "u" from the original integration formula...
Using the integrate() function seems more intuitive, but if I try:
u <- 1
integrand <- function(P) {u*P}
q <- integrate(integrand, lower = 0, upper = Inf)
I get this error:
# Error in integrate(integrand, lower = 0, upper = Inf) :
# the integral is probably divergent
As you can tell, I'm pretty lost, so any help would be greatly appreciated! Thank you so much! :)
integrand is technically acceptable but right now, it's the identity function f(x) = x. The area under it from [0, inf) is infinite, i.e. divergent.
From the documentation of integrate the first argument is:
an R function taking a numeric first argument and returning a numeric vector of the same length. Returning a non-finite element will generate an error.
If instead you use a pulse function:
pulse <- function(x) {ifelse(x < 5 & x >= 0, 1, 0)}
integrate(pulse, lower = 0, upper = Inf)
#> 5 with absolute error < 8.5e-05

Generating a function via for-loop for the Jacobian matrix in R

Suppose I have the following two variables y and z and the variable x
y = 1:10
z = 1:10
Now I would like to create a jacobian of the following function
f <- function(x) c(y[1]*x[1]+z[1]*x[2],
y[2]*x[1]+z[2]*x[2],
: : : :
y[10]*x[1]+z[10]*x[2])
Then obtaining the Jacobian can be easily obtained by
jacobian(f, c(1,1))
Now suppose
y= 1:i.
When i becomes large, computing the function manually becomes a time-consuming task.
Is there a way to construct the same function for i?
I tried the following:
for (i in 1:10) {
f[i] <- function(x) c(y[i]*x[1]+z[i]*x[2])
}
jacobian(f, c(1,1))
ThomasIsCoding suggests:
f <- function(x) tcrossprod(cbind(y, z), t(x))
Which works perfectly for this case.
Now suppose that the function is more complex
y[1]*x[1]^2+z[1]/x[2]
The t(x) suggested does no longer work. How do I now write a vector for x?
You can try the following way for function f
f <- function(x) tcrossprod(cbind(y, z), t(x))

Vectorising density of mixture Gaussian distribution and integrating/plotting in R

I'm trying to write the density of a mixture Gaussian distribution to an arbitrary power, b, in R. Currently, I have two methods that works, but I prefer if I could avoid a for loop.
dnorm_mix_tempered_unnorm <- function(x, w, m, s, b) {
value <- 0
for (i in 1:length(w)) {value <- value + w[i]*dnorm(x, mean = m[i], sd = s[i])}
value <- value^(b)
return(value)
}
Alternatively, I can vectorise this to avoid the for loop:
dnorm_mix_tempered_unnorm <- function(x, w, m, s, b) {
return(sum(w*dnorm(x, mean = m, sd = s))^b)
}
Both of these give the same result, but the second is more efficient since it is vectorised. But I need to next normalise this so that the density integrates to 1, I do this by using:
dnorm_mix_tempered <- function(x, weights, means, sds, beta) {
norm_constant <- integrate(function(x) dnorm_mix_tempered_unnorm(x, w = weights,
m = means, s = sds, b = 1/beta), lower = -Inf,
upper = Inf)$value
value <- dnorm_mix_tempered_unnorm(x, w = weights, m = means, s = sds, b = 1/beta)
/ norm_constant
return(value)
}
If I define dnorm_mix_tempered_unnorm with for loops, this works with no problem, and I can use curve() to plot the density. But if I define dnorm_mix_tempered_unnorm by using vectorisation, then I get the following error:
Error in integrate(function(x) dnorm_mix_tempered_unnorm(x, w = weights, :
evaluation of function gave a result of wrong length
Does anyone know what is going on when I am vectorising instead and trying to integrate?
Thanks in advance,
R.
A possible option is
dnorm_mix_tempered_unnorm <- function(x, w, m, s, b) {
return(rowSums(mapply(dnorm, mean = m, sd = m, MoreArgs = list(x = x)))^b)
}
But I think it is quite similar to your first proposal.

issues with numerical integration of multi-variable function in R

So, I have this function;
f <- function(a, b, q=1, f0=1000) {
#calculate R:
R <- (f0 - (a*b))*((q+1)/(a^(q+1)))
return(ifelse(a<=100,(R * a^q) + b, 0)) }
I am using it in another function, funk2
funk2 <- function(a,x,b,l,r) {
f(a-x,b) * exp(-(l/r)*(exp(-r*a)*(exp(r*x)-1))) }
funk2 is then used to evaluate another multi-variable function funk1 using integration;
funk1 <- function(x,b,l,r) {
sapply(x, function (s) {
integrate(funk2, lower = s, upper = s+56, x=s, b=b, l=l, r=r)$value }) }
when I try to evaluate funk1
funk1(10,100,1,1)
{or by putting any other values} I get an error saying that
Error in integrate(funk2, lower = s, upper = s + 100, x = s, b = b,
non-finite function value
I am not sure what am I doing wrong here? Please help!
Thanks in advance.
The problem is in f(a-x,b) inside funk2 when a is equal to x then f(0,b) will produce NaN. For example, if you modify your lower to lower = s*1.01 you get:
funk1(10,100,1,1)
[1] 4464.721

Error in seq.default(a, b, by = h) : 'to' cannot be NA, NaN or infinite

I have a two functions one is to calculate the integration and another one is fixed-point method to find the root.This is the function to calculate the integration:
trapezoid <- function(fun, a, b, n=100) {
h <- (b-a)/n
x <- seq(a, b, by=h)
y <- fun(x)
s <- h * (y[1]/2 + sum(y[2:n]) + y[n+1]/2)
return(s)
}
And this is the root finding function:
fixedpoint <- function(fun, x0, tol=1e-03, niter=5000){
## fixed-point algorithm to find x such that fun(x) == x
## assume that fun is a function of a single variable
## x0 is the initial guess at the fixed point
xold <- x0
xnew <- fun(xold)
for (i in 1:niter) {
xold <- xnew
xnew <- fun(xold)
if ( abs((xnew-xold)) < tol )
return(xnew)
}
stop("exceeded allowed number of iterations")
}
Now I define a function f f<-function(x) {x^2}
And get its integration function h<-function(x) trapezoid(f,2,x)
Last I want to find the roots of h by doingfixedpoint(h,2)
But I got the error message like this:
Error in seq.default(a, b, by = h) : 'to' cannot be NA, NaN or
infinite

Resources