이 스레드의 다른 곳에서 포인트를 서브 샘플링 하는 간단하지만 다소 임시적인 솔루션을 제안했습니다 . 빠르지 만 훌륭한 음모를 만들려면 약간의 실험이 필요합니다. 설명 될 해결책은 10 배 더 느리지 만 (120 만 포인트 동안 최대 10 초 소요) 적응 적이고 자동적입니다. 대규모 데이터 세트의 경우 처음에는 좋은 결과를 제공하고 합리적으로 신속하게 수행해야합니다.
아이디어는 Douglas-Peucker 의 아이디어입니다. 디엔
의 극값을 연결하는 선 사이의 최대 수직 편차를 찾습니다( x , y)티와이
특히 길이가 다른 데이터 세트에 대처하기 위해 처리해야 할 세부 사항이 있습니다. 나는 더 짧은 것을 더 긴 것에 대응하는 Quantile로 대체함으로써 이것을한다 : 사실상, 더 짧은 것의 EDF의 부분 선형 근사가 실제 데이터 값 대신에 사용된다. ( "짧게"및 "더 길게"를 설정하면 반전 할 수 있습니다.use.shortest=TRUE
.)
R
구현 은 다음과 같습니다 .
qq <- function(x0, y0, t.y=0.0005, use.shortest=FALSE) {
qq.int <- function(x,y, i.min,i.max) {
# x, y are sorted and of equal length
n <-length(y)
if (n==1) return(c(x=x, y=y, i=i.max))
if (n==2) return(cbind(x=x, y=y, i=c(i.min,i.max)))
beta <- ifelse( x[1]==x[n], 0, (y[n] - y[1]) / (x[n] - x[1]))
alpha <- y[1] - beta*x[1]
fit <- alpha + x * beta
i <- median(c(2, n-1, which.max(abs(y-fit))))
if (abs(y[i]-fit[i]) > thresh) {
assemble(qq.int(x[1:i], y[1:i], i.min, i.min+i-1),
qq.int(x[i:n], y[i:n], i.min+i-1, i.max))
} else {
cbind(x=c(x[1],x[n]), y=c(y[1], y[n]), i=c(i.min, i.max))
}
}
assemble <- function(xy1, xy2) {
rbind(xy1, xy2[-1,])
}
#
# Pre-process the input so that sorting is done once
# and the most detail is extracted from the data.
#
is.reversed <- length(y0) < length(x0)
if (use.shortest) is.reversed <- !is.reversed
if (is.reversed) {
y <- sort(x0)
n <- length(y)
x <- quantile(y0, prob=(1:n-1)/(n-1))
} else {
y <- sort(y0)
n <- length(y)
x <- quantile(x0, prob=(1:n-1)/(n-1))
}
#
# Convert the relative threshold t.y into an absolute.
#
thresh <- t.y * diff(range(y))
#
# Recursively obtain points on the QQ plot.
#
xy <- qq.int(x, y, 1, n)
if (is.reversed) cbind(x=xy[,2], y=xy[,1], i=xy[,3]) else xy
}
예를 들어 이전 답변과 같이 시뮬레이트 된 데이터를 사용합니다 ( 이때 극도로 높은 특이 치가 발생 y
하고 약간 더 많은 오염 x
이 발생합니다).
set.seed(17)
n.x <- 1.21 * 10^6
n.y <- 1.20 * 10^6
k <- floor(0.01*n.x)
x <- c(rnorm(n.x-k), rnorm(k, mean=2, sd=2))
x <- x[x <= -3 | x >= -2.5]
y <- c(rbeta(n.y, 10,13), 1)
더 작고 작은 임계 값을 사용하여 여러 버전을 플로팅합시다. 값이 .0005이고 높이가 1000 픽셀 인 모니터에 표시되면 하면 플롯의 모든 위치에서 수직 픽셀의 절반 이하의 오류 보장 됩니다. 이것은 회색으로 표시됩니다 (선 세그먼트로 결합 된 522 포인트 만). 거칠기 근사치가 그 위에 표시됩니다. 먼저 검은 색, 빨간색으로 표시됩니다 (빨간색 점은 검은 색 점의 하위 집합이되고 오버 플롯이 됨). 타이밍 범위는 6.5 (파란색)에서 10 초 (회색)입니다. 그것들이 너무 잘 확장되면, 임계 값에 대한 보편적 인 기본값 ( 예를 들어 , 1000- 픽셀 높이 모니터의 경우 1/2000)과 마찬가지로 약 1/2 픽셀을 사용할 수 있습니다.
qq.1 <- qq(x,y)
plot(qq.1, type="l", lwd=1, col="Gray",
xlab="x", ylab="y", main="Adaptive QQ Plot")
points(qq.1, pch=".", cex=6, col="Gray")
points(qq(x,y, .01), pch=23, col="Black")
points(qq(x,y, .03), pch=22, col="Red")
points(qq(x,y, .1), pch=19, col="Blue")
편집하다
qq
인덱스의 세 번째 열을 원래 두 배열 중 가장 긴 (또는 지정된대로 가장 짧은) x
및 y
선택한 점에 대응하도록 원래 코드를 수정했습니다 . 이 인덱스는 데이터의 "관심있는"값을 가리 키므로 추가 분석에 유용 할 수 있습니다.
또한 x
( beta
정의되지 않은) 반복 값으로 발생하는 버그를 제거했습니다 .
approx()
함수 에서 함수가qqplot()
작동합니다.