R의 고유 값과 고유 벡터에서 타원을 그리는 방법은 무엇입니까? [닫은]


15

누군가가 마련 수 R의 고유 값으로부터 타원과 같은 행렬의 고유 벡터 플롯 코드

=(2.20.40.42.8)

답변:


16

를 통해 고유 벡터와 값을 추출 할 수 있습니다 eigen(A). 그러나 Cholesky 분해를 사용하는 것이 더 간단합니다. 데이터에 대한 신뢰 타원을 플로팅 할 때 타원 축은 일반적으로 해당 고유 값의 길이 = 제곱근을 갖도록 크기가 조정되며 이것이 Cholesky 분해가 제공하는 것입니다.

ctr    <- c(0, 0)                               # data centroid -> colMeans(dataMatrix)
A      <- matrix(c(2.2, 0.4, 0.4, 2.8), nrow=2) # covariance matrix -> cov(dataMatrix)
RR     <- chol(A)                               # Cholesky decomposition
angles <- seq(0, 2*pi, length.out=200)          # angles for ellipse
ell    <- 1 * cbind(cos(angles), sin(angles)) %*% RR  # ellipse scaled with factor 1
ellCtr <- sweep(ell, 2, ctr, "+")               # center ellipse to the data centroid
plot(ellCtr, type="l", lwd=2, asp=1)            # plot ellipse
points(ctr[1], ctr[2], pch=4, lwd=2)            # plot data centroid

library(car)  # verify with car's ellipse() function
ellipse(c(0, 0), shape=A, radius=0.98, col="red", lty=2)

편집 : 고유 벡터를 플로팅하려면보다 복잡한 접근법을 사용해야합니다. 이것은 suncoolsu의 답변과 동일하며 매트릭스 표기법을 사용하여 코드를 단축합니다.

eigVal  <- eigen(A)$values
eigVec  <- eigen(A)$vectors
eigScl  <- eigVec %*% diag(sqrt(eigVal))  # scale eigenvectors to length = square-root
xMat    <- rbind(ctr[1] + eigScl[1, ], ctr[1] - eigScl[1, ])
yMat    <- rbind(ctr[2] + eigScl[2, ], ctr[2] - eigScl[2, ])
ellBase <- cbind(sqrt(eigVal[1])*cos(angles), sqrt(eigVal[2])*sin(angles)) # normal ellipse
ellRot  <- eigVec %*% t(ellBase)                                          # rotated ellipse
plot((ellRot+ctr)[1, ], (ellRot+ctr)[2, ], asp=1, type="l", lwd=2)
matlines(xMat, yMat, lty=1, lwd=2, col="green")
points(ctr[1], ctr[2], pch=4, col="red", lwd=3)

여기에 이미지 설명을 입력하십시오


이 타원에 고유 값과 고유 벡터를 플로팅 하시겠습니까? 감사합니다
MYaseen208

@ MYaseen208 고유 벡터를 타원의 축으로 표시하도록 답변을 편집했습니다. 축 길이의 절반은 해당 고유 벡터의 제곱근과 같습니다.
caracal

7

나는 이것이 당신이 원하는 R 코드라고 생각합니다. 이메일 목록에있는 이 스레드 에서 R 코드를 빌 렸습니다 . 아이디어는 기본적으로 주 및 보조 반 직경이 두 고유 값이며 첫 번째 고유 벡터와 x 축 사이의 각도만큼 타원을 회전시킵니다.

mat <- matrix(c(2.2, 0.4, 0.4, 2.8), 2, 2)
eigens <- eigen(mat)
evs <- sqrt(eigens$values)
evecs <- eigens$vectors

a <- evs[1]
b <- evs[2]
x0 <- 0
y0 <- 0
alpha <- atan(evecs[ , 1][2] / evecs[ , 1][1])
theta <- seq(0, 2 * pi, length=(1000))

x <- x0 + a * cos(theta) * cos(alpha) - b * sin(theta) * sin(alpha)
y <- y0 + a * cos(theta) * sin(alpha) + b * sin(theta) * cos(alpha)


png("graph.png")
plot(x, y, type = "l", main = expression("x = a cos " * theta * " + " * x[0] * " and y = b sin " * theta * " + " * y[0]), asp = 1)
arrows(0, 0, a * evecs[ , 1][2], a * evecs[ , 1][2])
arrows(0, 0, b * evecs[ , 2][3], b * evecs[ , 2][2])
dev.off()

여기에 이미지 설명을 입력하십시오


자유롭게 고쳐주세요. 나는 고유의 vec가 수직이라고 생각하지 않습니다 (그들은 이론에 있어야합니다; 내가 뭔가 잘못하고 있습니까?).
suncoolsu

답장을 보내 주셔서 감사합니다. 이 타원은 멋져 보이지만 뭔가 빠졌습니다. 이 행렬 주어진 코드를 시도 그리고 올바른 타원을 제공했습니다. 왜 행렬의 다른 분산에 올바른 타원을 제공하지 않는지 궁금합니다. 모든 의견! =(1551)
MYaseen208

다만 설정 asp=1한 수직 화살표의 종횡비를 갖도록. evs <- sqrt(eigens$values)내 답변과 동일한 타원 을 제공하도록 코드를 변경하십시오 .
caracal

3
@ MYaseen208 새 행렬은 양의 한정이 아닙니다. 음의 고유 값을 가지며 공분산 행렬이 아닙니다. 이 경우 어떤 타원을 그릴 지 모르겠습니다.
caracal

@caracal 감사합니다! ... 그래-나는 sqrt 부분을 놓쳤다!
suncoolsu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.