让我们用两个变量画一张图。 它将说明总体思路。
为了实现这一点,我生成了一组 500 个预期相关性为的数据,计算了第一个主成分 (PC),将其分成五个等量的 bin,并为每个 bin 计算了第一个 PC。0.25

第一个 PC(未直接显示)沿所有点云的主轴指向。箱之间的边界是垂直于该方向的线。 这些以白色显示。他们将平面划分为五个区域,按区域分配点并为其着色。每个 bin 中点的第一个 PC 用一个箭头表示,该箭头起始于 bin 点的质心。(质心用黑点标记。)
这种“去相关”任何事物的意义尚不清楚,因为 - 正如在图中很明显 - 每个 bin 内的点可能(如果有的话)比原始点更相关。此过程确实根据数据沿点云主轴的位置对数据进行分层,从而消除沿主轴变化的大部分影响:也许这在应用程序中完成了一些有用的事情。
编写代码以实现模拟参数的R变化:点数、相关系数和箱数。我提供它以用于进一步探索这种情况。
library(MASS) # Generates multivariate Normal data
library(ggplot2) # Plots nicely
library(data.table) # Computes on data frames well
#
# Specify the multivariate data distribution.
#
n <- 5e2 # Sample size
mu <- c(0,0) # Mean
rho <- 0.25 # Correlation coefficient
n.bins <- 5 # Number of bins
#
# Generate correlated variables.
#
X <- as.data.table(mvrnorm(n, mu, matrix(c(1,rho,rho,1), 2))) # Observations
#
# Compute the first PC.
#
P <- prcomp(X, rank.=1)
X$PC1 <- t(t(X) - P$center) %*% P$rotation
#
# Bin the first principal component.
#
n.bins <- min(n.bins, n)
q <- quantile(X$PC1, seq(0, 1, length.out=n.bins+1))
q[1] <- -Inf; q[n.bins+1] <- Inf
X$Bin <- cut(X$PC1, q)
#
# Create a data frame for plotting the bin boundaries.
#
beta <- P$rotation
Q <- data.table(intercept=q[-c(1,n.bins+1)]/beta[2], slope=-beta[1]/beta[2])
#
# Do PCA by bin.
#
f <- function(x, y, length=1.5) {
s <- sign(cor(x,y))
slope <- s * sd(y) / sd(x)
intercept <- mean(y) - mean(x) * slope
list(x=mean(x), y=mean(y), xend=mean(x)+length*s*sd(x), yend=mean(y)+length*sd(y))
}
#
# Create a data frame for plotting the bin PCs.
#
P <- X[, c(f(V1, V2)), by=Bin]
#
# Plot the data and the results.
#
g <- ggplot(X, aes(V1, V2, group=Bin, color=Bin)) +
geom_abline(aes(intercept=intercept, slope=slope), data=Q,
size=1, color="White", alpha=0.9) +
geom_segment(aes(x=x, y=y, xend=xend, yend=yend), data=P,
size=1.25, arrow = arrow(length = unit(0.02, "npc"))) +
geom_point(aes(x, y), data=P, shape=19, size=1.5, color="Black") +
geom_point(alpha=0.4) +
coord_fixed() +
ggtitle("Bins of the First PC",
"First PC of Each Bin Shown With Arrows") +
theme(panel.grid=element_blank())
print(g)