gpt4 book ai didi

R - `prcomp` 是否采用样本数据或协方差矩阵作为输入?

转载 作者:行者123 更新时间:2023-12-02 01:10:19 29 4
gpt4 key购买 nike

如果您在线搜索,有一些线程讨论了函数 princomp 中使用 covmat 标志,该函数对其输入执行主成分分析。如果未定义 covmat 参数,princomp 首先计算输入的样本协方差矩阵。

另一方面,几乎没有讨论类似的函数 prcomp 实际上如何完成数据主成分分析的任务,只讨论它是否更准确比princomp。这就引出了一个问题:prcomp 是否采用协方差矩阵或样本数据矩阵作为输入?帮助文档中并不清楚,它指出(在非公式上下文中):

Default S3 method:

prcomp(x, retx = TRUE, center = TRUE, scale. = FALSE,
tol = NULL, ...)

x - a numeric or complex matrix (or data frame) which provides the data for the principal components analysis.

帮助文件不包含此方法的任何示例,仅包含上面记录的适用于公式对象的示例。文档有点暗示预期的输入是协方差矩阵,如下所示:

The calculation is done by a singular value decomposition of the (centered and possibly scaled) data matrix, not by using eigen on the covariance matrix.

但是,尚不清楚“数据矩阵”是否是“协方差矩阵”,以及“数据矩阵”是否表示文档前面部分给出的 x

最佳答案

幸运的是,答案可以在这两个函数的源代码中找到。

首先,prcomp的来源:

> stats:::prcomp.default
function (x, retx = TRUE, center = TRUE, scale. = FALSE, tol = NULL,
...)
{
x <- as.matrix(x)
x <- scale(x, center = center, scale = scale.)
cen <- attr(x, "scaled:center")
sc <- attr(x, "scaled:scale")
if (any(sc == 0))
stop("cannot rescale a constant/zero column to unit variance")
s <- svd(x, nu = 0)
s$d <- s$d/sqrt(max(1, nrow(x) - 1))
if (!is.null(tol)) {
rank <- sum(s$d > (s$d[1L] * tol))
if (rank < ncol(x)) {
s$v <- s$v[, 1L:rank, drop = FALSE]
s$d <- s$d[1L:rank]
}
}
dimnames(s$v) <- list(colnames(x), paste0("PC", seq_len(ncol(s$v))))
r <- list(sdev = s$d, rotation = s$v, center = if (is.null(cen)) FALSE else cen,
scale = if (is.null(sc)) FALSE else sc)
if (retx)
r$x <- x %*% s$v
class(r) <- "prcomp"
r
}

请注意,上面的 block 中没有执行协方差计算。对所提供的输入执行缩放和居中操作,此时对结果调用奇异值分解 (SVD) 函数。下一步是根据对角化结果的等级检查结果的大小,以确保结果有效。最后,输出被格式化并设置为适当的类。

换句话说,prcomp 是对协方差矩阵简单调用 SVD 的一个很好的改进,但不会为您计算协方差矩阵。 prcomp 不是对数据调用,而是对某些数据的协方差估计进行调用。

编辑:被删除的句子是错误的!在这种情况下,不需要形成协方差矩阵,如果我正确戴上数学帽子,我就会意识到这一点!有关原因的解释,请参阅 this math.SO thread 。在数据矩阵上使用 SVD 计算主成分在这里肯定更有效。

princomp 中的代码比较(仅显示一部分):

if (is.list(covmat)) {
if (any(is.na(match(c("cov", "n.obs"), names(covmat)))))
stop("'covmat' is not a valid covariance list")
cv <- covmat$cov
n.obs <- covmat$n.obs
cen <- covmat$center
}
else if (is.matrix(covmat)) {
if (!missing(x))
warning("both 'x' and 'covmat' were supplied: 'x' will be ignored")
cv <- covmat
n.obs <- NA
cen <- NULL
}
else if (is.null(covmat)) {
dn <- dim(z)
if (dn[1L] < dn[2L])
stop("'princomp' can only be used with more units than variables")
covmat <- cov.wt(z)
n.obs <- covmat$n.obs
cv <- covmat$cov * (1 - 1/n.obs)
cen <- covmat$center
}

正如您所看到的,princomp 函数根据输入的传递方式执行更多操作,这需要更加小心。

关于R - `prcomp` 是否采用样本数据或协方差矩阵作为输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19896410/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com