nearPD package:Matrix R Documentation _N_e_a_r_e_s_t _M_a_t_r_i_x _t_o _a _P_o_s_i_t_i_v_e _D_e_f_i_n_i_t_e _M_a_t_r_i_x _D_e_s_c_r_i_p_t_i_o_n: Computes the nearest positive definite matrix to an approximate one, typically a correlation or variance-covariance matrix. _U_s_a_g_e: nearPD(x, corr = FALSE, keepDiag = FALSE, do2eigen = TRUE, only.values = FALSE, eig.tol = 1e-06, conv.tol = 1e-07, posd.tol = 1e-08, maxit = 100, trace = FALSE) _A_r_g_u_m_e_n_t_s: x: numeric n * n approximately positive definite matrix, typically an approximation to a correlation or covariance matrix. corr: logical indicating if the matrix should be a _correlation_ matrix. keepDiag: logical, generalizing 'corr': if 'TRUE', the resulting matrix should have the same diagonal ('diag(x)') as the input matrix. do2eigen: logical indicating if a 'posdefify()' eigen step should be applied to the result of the Higham algorithm. only.values: logical; if 'TRUE', the result is just the vector of eigen values of the approximating matrix. eig.tol: defines relative positiveness of eigenvalues compared to largest one, lambda_1. Eigen values lambda_k are treated as if zero when lambda_k / lambda_1 <= eig.tol. conv.tol: convergence tolerance for Higham algorithm. posd.tol: tolerance for enforcing positive definiteness (in the final 'posdefify' step when 'do2eigen' is 'TRUE'). maxit: maximum number of iterations allowed. trace: logical or integer specifying if convergence monitoring should be traced. _D_e_t_a_i_l_s: This implements the algorithm of Higham (2002), and then forces positive definiteness using code from 'posdefify'. The algorithm of Knol DL and ten Berge (1989) (not implemented here) is more general in (1) that it allows constraints to fix some rows (and columns) of the matrix and (2) to force the smallest eigenvalue to have a certain value. Note that setting 'corr = TRUE' just sets 'diag(.) <- 1' within the algorithm. _V_a_l_u_e: If 'only.values = TRUE', a numeric vector of eigen values of the approximating matrix; Otherwise, as by default, an S3 object of 'class' '"nearPD"', basically a list with components mat: a matrix of class 'dpoMatrix', the computed positive-definite matrix. eigenvalues: numeric vector of eigen values of 'mat'. corr: logical, just the argument 'corr'. normF: the Frobenius norm ('norm(x-X, "F")') of the difference between the original and the resulting matrix. iterations: number of iterations needed. converged: logical indicating if iterations converged. _A_u_t_h_o_r(_s): Jens Oehlschlaegel donated a first version. Subsequent changes by the Matrix package authors. _R_e_f_e_r_e_n_c_e_s: Cheng, Sheung Hun and Higham, Nick (1998) A Modified Cholesky Algorithm Based on a Symmetric Indefinite Factorization; _SIAM J. Matrix Anal. Appl._, *19*, 1097-1110. Knol DL, ten Berge JMF (1989) Least-squares approximation of an improper correlation matrix by a proper one. _Psychometrika_ *54*, 53-61. Higham, Nick (2002) Computing the nearest correlation matrix - a problem from finance; _IMA Journal of Numerical Analysis_ *22*, 329-343. _S_e_e _A_l_s_o: A first version of this (with non-optional 'corr=TRUE') has been available as 'nearcor()'; and more simple versions with a similar purpose 'posdefify()', both from package 'sfsmisc'. _E_x_a_m_p_l_e_s: set.seed(27) m <- matrix(round(rnorm(25),2), 5, 5) m <- m + t(m) diag(m) <- pmax(0, diag(m)) + 1 (m <- round(cov2cor(m), 2)) str(near.m <- nearPD(m, trace = TRUE)) round(near.m$mat, 2) norm(m - near.m$mat) # 1.102 if(require("sfsmisc")) { m2 <- posdefify(m) # a simpler approach norm(m - m2) # 1.185, i.e., slightly "less near" } round(nearPD(m, only.values=TRUE), 9) ## A longer example, extended from Jens' original, ## showing the effects of some of the options: pr <- Matrix(c(1, 0.477, 0.644, 0.478, 0.651, 0.826, 0.477, 1, 0.516, 0.233, 0.682, 0.75, 0.644, 0.516, 1, 0.599, 0.581, 0.742, 0.478, 0.233, 0.599, 1, 0.741, 0.8, 0.651, 0.682, 0.581, 0.741, 1, 0.798, 0.826, 0.75, 0.742, 0.8, 0.798, 1), nrow = 6, ncol = 6) nc. <- nearPD(pr, conv.tol = 1e-7) # default nc.$iterations # 2 nc.1 <- nearPD(pr, conv.tol = 1e-7, corr = TRUE) nc.1$iterations # 11 (!) ncr <- nearPD(pr, conv.tol = 1e-15) str(ncr)# 3 iterations ncr.1 <- nearPD(pr, conv.tol = 1e-15, corr = TRUE) ncr.1 $ iterations # 27 ! ## But indeed, the 'corr = TRUE' constraint did ensure a better solution; ## cov2cor() does not just fix it up equivalently : norm(pr - cov2cor(ncr$mat)) # = 0.09994 norm(pr - ncr.1$mat) # = 0.08746