Tengo una distribución normal bivariada compuesta por las distribuciones normales univariadas $X_1$ y $X_2$ con $\rho \approx 0.3$ .
$$ \begin{pmatrix} X_1 \\ X_2 \end{pmatrix} \sim \mathcal{N} \left( \begin{pmatrix} \mu_1 \\ \mu_2 \end{pmatrix} , \begin{pmatrix} \sigma^2_1 & \rho \sigma_1 \sigma_2 \\ \rho \sigma_1 \sigma_2 & \sigma^2_2 \end{pmatrix} \right) $$
¿Existe una forma sencilla de calcular en R la probabilidad acumulada de $X_1$ siendo menor que un valor $z$ dada una porción particular de $X_2$ (entre dos valores $a,b$ ) dado que conocemos todos los parámetros $\mu_1, \mu_2, \sigma_1, \sigma_2, \rho$ ?
$P(X_1 < z | a < X_2 < b)$
¿Puede la función de distribución que busco coincidir (o ser aproximada por) la función de distribución de una distribución normal univariante (para usar qnorm
/ pnorm
)? Lo ideal sería que fuera así para poder realizar el cálculo con menos dependencias de bibliotecas (por ejemplo, en un servidor MySQL).
Esta es la distribución bivariada que estoy utilizando:
means <- c(79.55920, 52.29355)
variances <- c(268.8986, 770.0212)
rho <- 0.2821711
covariancePartOfMatrix <- sqrt(variances[1]) * sqrt(variances[2]) * rho
sigmaMatrix <- matrix(c(variances[1],covariancePartOfMatrix,covariancePartOfMatrix,variances[2]), byrow=T, ncol=2)
n <- 10000
dat <- MASS::mvrnorm(n=n, mu=means, Sigma=sigmaMatrix)
plot(dat)
Este es mi intento numérico de obtener el resultado correcto. Sin embargo, utiliza datos generados de la distribución bivariada y no estoy convencido de que dé el resultado correcto.
a <- 79.5
b <- 80.5
z <- 50
sliceOfDat <- subset(data.frame(dat), X1 > a, X1 < b)
estimatedMean <- mean(sliceOfDat[,c(2)])
estimatedDev <- sd(sliceOfDat[,c(2)])
estimatedPercentile <- pnorm(z, estimatedMean, estimatedDev)
Edición - Implementación en R de la solución basada en la respuesta de whuber
A continuación se presenta una implementación de la solución aceptada utilizando integrate
comparado con mi idea original basada en el muestreo. La solución aceptada proporciona el resultado esperado 0,5, mientras que mi idea original se desviaba en una cantidad significativa (0,41). Actualización - Ver la edición de wheber para una mejor implementación.
# Bivariate distribution parameters
means <- c(79.55920, 52.29355)
variances <- c(268.8986, 770.0212)
rho <- 0.2821711
# Generate sample data for bivariate distribution
n <- 10000
covariancePartOfMatrix <- sqrt(variances[1]) * sqrt(variances[2]) * rho
sigmaMatrix <- matrix(c(variances[1],covariancePartOfMatrix,covariancePartOfMatrix,variances[2]), byrow=T, ncol=2)
dat <- MASS::mvrnorm(n=n, mu=means, Sigma=sigmaMatrix)
# Input parameters to test the estimation
w = 79.55920
a <- w - 0.5
b <- w + 0.5
z <- 52.29355
# Univariate approximation using randomness
sliceOfDat <- subset(data.frame(dat), X1 > a, X1 < b)
estimatedMean <- mean(sliceOfDat[,c(2)])
estimatedDev <- sd(sliceOfDat[,c(2)])
estimatedPercentile <- pnorm(z, estimatedMean, estimatedDev)
# OUTPUT: 0.411
# Numerical approximation from exact solution
adaptedZ <- (z - means[2]) / sqrt(variances[2])
adaptedB <- (b - means[1]) / sqrt(variances[1])
adaptedA <- (a - means[1]) / sqrt(variances[1])
exactSolutionCoeff <- 1 / (pnorm(adaptedB) - pnorm(adaptedA))
integrand <- function(x) pnorm((adaptedZ - rho * x) / sqrt(1 - rho * rho)) * dnorm(x)
exactSolutionInteg <- integrate(integrand, adaptedA, adaptedB)
# 0.0121, abs.error 1.348036e-16, "OK"
exactPercentile = exactSolutionCoeff * exactSolutionInteg$value
# OUTPUT: 0.500