Integration of function when matrix is included in R - r

I want to integrate a function which looks like
f <- function(x) 1.96 * sqrt(t(c(1,x)) %*% m %*% c(1,x))
where m is
m <- matrix(c(3.855, -0.206, -0.206, 0.01), nrow = 2, ncol = 2, byrow = T)
Since the matrix multiplication inside my function produces a scalar, for any value of x, this is just a one-dimensional integration for f(x). How can I solve this smoothly?

Simply with integrate and Vectorize:
integrate(Vectorize(f), lower = 0, upper = 1)

Here is another option without Vectorize (but I believe the approach by #Stéphane Laurent is more space-efficient)
> ff <- function(x) 1.96 * sqrt(diag(t(rbind(1, x)) %*% m %*% rbind(1, x)))
> integrate(ff, lower = 0, upper = 1)
3.745299 with absolute error < 4.2e-14
where ff is already a vectorized function since it is constructed using rbind + diag to accept vector argument.

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

Derive the value of a parameter to reach a specific result of a function in R (v.4.2.1)

I need to find the value of a parameter which make my function produce a specific result.
I write down something like this:
## Defining the function
f = function(a, b, c, x) sqrt(t(c(a, b, c, x)) %*% rho %*% c(a, b, c, x))
## Set di input needed
rho <- matrix(c(1,0.3,0.2,0.4,
0.3,1,0.1,0.1,
0.2,0.1,1,0.5,
0.4,0.1,0.5,1),
nrow = 4, ncol = 4)
target <- 10000
## Optimize
output <- optimize(f, c(0, target), tol = 0.0001, a = 1000, b = 1000, c = 1000, maximum = TRUE)
I would like to derive di value of x related to the maximum of my function (the target value).
Thanks,
Ric
You can find one such x with closed formula. For symmetric matrices (like the one you have) you can achieve target value by vector x where x is defined as:
spectral_decomp <- eigen(rho, TRUE)
eigen_vec1 <- spectral_decomp$vectors[,1]
lambda1 <- spectral_decomp$values[[1]]
target <- 1000
x <- (target / sqrt(lambda1)) * eigen_vec1
check:
sqrt(matrix(x, nrow = 1) %*% rho %*% matrix(x, ncol = 1))

statistical formula for scale function in R

what is mathematical formula of scale in R? I just tried the following but it is not the same as scale(X)
( X-colmeans(X))/ sapply(X, sd)
Since vector subtraction from matrices/data-frames works column-wise instead of row-wise, you have to transpose the matrix/data-frame before subtraction and then transpose back at the end. The result is the same as scale except for rounding errors. This is obviously a hassle to do, which I guess is why there's a convenience function.
x <- as.data.frame(matrix(sample(100), 10 , 10))
s <- scale(x)
my_s <- t((t(x) - colMeans(x))/sapply(x, sd))
all(s - my_s < 1e-15)
# [1] TRUE
1) For each column subtract its mean and then divide by its standard deviation:
apply(X, 2, function(x) (x - mean(x)) / sd(x))
2) Another way to write this which is fairly close to the code in the question is the following. The main difference between this and the question is that the question's code recycles by column (which is not correct in this case) whereas the following code recycles by row.
nr <- nrow(X)
nc <- ncol(X)
(X - matrix(colMeans(X), nr, nc, byrow = TRUE)) /
matrix(apply(X, 2, sd), nr, nc, byrow = TRUE)

Algebra behind MVRNorm in MASS package

Here's the code:
function (n = 1, mu, Sigma, tol = 1e-06, empirical = FALSE, EISPACK = FALSE)
{
p <- length(mu)
if (!all(dim(Sigma) == c(p, p)))
stop("incompatible arguments")
if (EISPACK)
stop("'EISPACK' is no longer supported by R", domain = NA)
eS <- eigen(Sigma, symmetric = TRUE)
ev <- eS$values
if (!all(ev >= -tol * abs(ev[1L])))
stop("'Sigma' is not positive definite")
X <- matrix(rnorm(p * n), n)
if (empirical) {
X <- scale(X, TRUE, FALSE)
X <- X %*% svd(X, nu = 0)$v
X <- scale(X, FALSE, TRUE)
}
X <- drop(mu) + eS$vectors %*% diag(sqrt(pmax(ev, 0)), p) %*%
t(X)
nm <- names(mu)
if (is.null(nm) && !is.null(dn <- dimnames(Sigma)))
nm <- dn[[1L]]
dimnames(X) <- list(nm, NULL)
if (n == 1)
drop(X)
else t(X)
}
The line in question I am curious about is this:
x <- eS$vectors %*% diag(sqrt(ev)) %*% t(x) # ignoring drop(mu)
...
t(x)
Why is it that
X^T = UVZ^T, where Z is a standardized MVN?
I had thought that this would be X = UVZ, where X ~ MVN(0, UV(I)(UV)^T) = MVN(0, Sigma)?
In response to Siong Thye Goh's answer:
I can see the algebra, and that it does work only doing it this way by just considering the dimensions, but the whole act of transposing everything seems strange to do considering the properties of a multivariate normal. That is, X = UVZ
I did some reviewing and I found that this is actually a Matrix Normal, and the affine transformation there works in the similar fashion. That is, X = Z (UV)^T.
I'm not sure if there is just something silly I'm missing in understanding this or if I'm missing the picture altogether on why everything is transposed in regards to, say, Wikipedias Affine Transformation of a MVN
U is the eigenvector of Sigma. That is Sigma = UV^2 U^T, where V is a diagonal matrix.
Let's compute the covariance matrix E[X^TX] and see if it is equal to Sigma where X=UVZ^T and Z^T satisfy E[Z^TZ]=I, the identity matrix.
We have
E[X^TX]=E[UVZ^TZVU^T]=UVE[Z^TZ]VU^T=UV^2U^T=Sigma

Speed-up inverse of weighted least squares covariance matrix in R

I need to speed up the calculation of the inverse of a WLS covariance matrix in R, where the matrix, wls.cov.matrix, is given by (full example below):
n = 10000
X = matrix(c(rnorm(n,1,2), sample(c(1,-1), n, replace = TRUE), rnorm(n,2,0.5)), nrow = 1000, ncol = 3)
Q = diag(rnorm(n, 1.5, 0.3))
wls.cov.matrix = solve(t(X)%*%diag(1/diag(Q))%*%X)
Is it possible to speed up this calculation?
MORE INFO VERY RELEVANT TO THE FINAL GOAL:
This is still little information, let me explain more my goal and will be clearer if there are ways to speed up my code.
I run 1,0000s of times wls.cov.matrix so I need it to be much faster.
However, each time I run it I use the same X, the only matrix that changes is Q, which is a diagonal matrix.
If X was a square matrix, of same dim as Q, I could just precompute X^-1 and (X^T)^(-1),
X.inv = solve(X)
X.inv.trans = solve(t(X))
and then for each iteration run:
Q.inv = diag(1/diag(Q))
wls.cov.matrix = X.inv%*%Q.inv%*%X.inv.trans
But my X is not square, so is there any other trick?
The main time-consuming part here is t(X)%*%diag(1/diag(Q))%*%X, not the calculation of its inverse.
A nice trick is to calculate it as
crossprod(X / sqrt(diag(Q)));
Confirmation:
all.equal( (t(X) %*% diag(1/diag(Q)) %*% X) , crossprod(X / sqrt(diag(Q))) );
[1] TRUE
To compare the timing run:
Qdiag = diag(Q);
system.time({(t(X) %*% diag(1/Qdiag) %*% X)})
system.time({crossprod(X / sqrt(Qdiag))})
Well, Q is a diagonal matrix, so its inverse is just given by the inverses of the diagonal entries. You can thus do
X = matrix(c(rnorm(n,1,2), sample(c(1,-1), n, replace = TRUE), rnorm(n,2,0.5)), nrow = 1000, ncol = 3)
Qinv = diag(1/rnorm(n, 1.5, 0.3))
wls.cov.matrix = solve(t(X)%*%Qinv%*%X)
And in fact, this speeds things up by about a factor of 20.

Resources