R语言特征分解:如何获取eigen()返回的未排序特征值
R语言计算股票相关矩阵未排序特征值方法
核心问题
R内置的eigen()函数计算矩阵特征值时,默认会将结果按特征值模的大小降序排列,没有提供关闭排序的参数,无法直接输出未排序、可与原矩阵列名(股票名称)按位置对应的特征值向量。
注意:特征值是矩阵的整体属性,不存在和单个列(单只股票)天然绑定的固有顺序,以下方法获取的「未排序特征值」是底层计算库输出的原始顺序结果,未经过
eigen()函数的降序重排,可直接匹配原矩阵的列名顺序。
实现代码
eigen()函数底层调用LAPACK线性代数库计算特征值,对于对称的相关矩阵,我们可以直接调用LAPACK的dsyevr接口,跳过R内置的排序步骤,拿到原始顺序的计算结果:
# 输入的股票相关矩阵 y = data.frame( AAPL = c(1.0000000, 0.8034606, 0.7004717, 0.6996925, 0.6671458, 0.4958710, 0.5433092, 0.6900178, 0.6376572, 0.6162418), MSFT = c(0.8034606, 1.0000000, 0.8219716, 0.8260105, 0.6896919, 0.4793830, 0.5699094, 0.7572619, 0.6680316, 0.6667194), GOOG = c(0.7004717, 0.8219716, 1.0000000, 0.9921730, 0.6429816, 0.4169146, 0.5442465, 0.6656362, 0.7031941, 0.6645946), GOOGL = c(0.6996925, 0.8260105, 0.9921730, 1.0000000, 0.6356657, 0.4127679, 0.5514112, 0.6729881, 0.6984569, 0.6616017), AMZN = c(0.6671458, 0.6896919, 0.6429816, 0.6356657, 1.0000000, 0.4392104, 0.4842821, 0.6302510, 0.6349091, 0.4030298), TSLA = c(0.4958710, 0.4793830, 0.4169146, 0.4127679, 0.4392104, 1.0000000, 0.4303702, 0.5205868, 0.3700049, 0.3608651), TSM = c(0.5433092, 0.5699094, 0.5442465, 0.5514112, 0.4842821, 0.4303702, 1.0000000, 0.6379209, 0.4380425, 0.4685874), NVDA = c(0.6900178, 0.7572619, 0.6656362, 0.6729881, 0.6302510, 0.5205868, 0.6379209, 1.0000000, 0.5819932, 0.5501563), FB = c(0.6376572, 0.6680316, 0.7031941, 0.6984569, 0.6349091, 0.3700049, 0.4380425, 0.5819932, 1.0000000, 0.5190931), V = c(0.6162418, 0.6667194, 0.6645946, 0.6616017, 0.4030298, 0.3608651, 0.4685874, 0.5501563, 0.5190931, 1.0000000)) # 转为矩阵格式 cor_mat <- as.matrix(y) n <- nrow(cor_mat) # 调用LAPACK接口计算未排序特征值 eigen_res <- .Fortran("dsyevr", JOBZ = "N", # 仅计算特征值,不计算特征向量 RANGE = "A", # 计算所有特征值 UPLO = "U", # 使用矩阵上三角部分计算 N = as.integer(n), A = cor_mat, LDA = as.integer(n), VL = 0, VU = 0, IL = 0L, IU = 0L, ABSTOL = 0, M = integer(1), W = numeric(n), # 存储特征值结果 Z = matrix(0, nrow=1, ncol=1), LDZ = 1L, ISUPPZ = integer(2*n), WORK = numeric(26*n), LWORK = 26L*n, IWORK = integer(10*n), LIWORK = 10L*n, INFO = integer(1) ) # 提取未排序特征值,匹配股票名称 unsorted_eigen <- eigen_res$W names(unsorted_eigen) <- colnames(y)
结果验证
将得到的未排序特征值做降序排列,和eigen()默认返回的结果对比,二者完全一致即可验证计算准确:
all.equal(sort(unsorted_eigen, decreasing = TRUE), eigen(cor_mat)$values) # 运行返回TRUE即为验证通过
补充说明
如果你不需要严格的底层计算原始顺序,只是需要特征值和股票名称一一对应,也可以直接使用eigen()的计算结果,手动给结果赋予列名即可,但此时特征值是按大小降序排列的,不属于未排序结果。
内容的提问来源于stack exchange,提问作者mario19088
相关产品推荐
相关产品推荐

