이것을 간단한 조각으로 나누겠습니다. 그렇게함으로써, 모든 작업은 수십 줄의 쉽게 테스트 된 코드로 달성됩니다.
먼저 거리를 계산해야합니다. 데이터가 지리적 좌표로되어 있으므로 다음은 Haversine 공식을 사용하여 구면 데이텀의 거리를 계산하는 함수입니다.
#
# Spherical distance.
# `x` and `y` are (long, lat) pairs *in radians*.
dist <- function(x, y, R=1) {
d <- y - x
a <- sin(d[2]/2)^2 + cos(x[2])*cos(y[2])*sin(d[1]/2)^2
return (R * 2*atan2(sqrt(a), sqrt(1-a)))
}
원하는 경우 (예를 들어 타원체 데이텀을 사용하는) 선호하는 구현으로 바꾸십시오.
다음으로, 각 "기준점"(계단이 확인 됨)과 시간적 이웃 사이의 거리를 계산해야합니다. 그것은 단순히 dist
이웃 에 적용하는 문제입니다 .
#
# Compute the distances between an array of locations and a base location `x`.
dist.array <- function(a, x, ...) apply(a, 1, function(y) dist(x, y, ...))
셋째, 이것이 핵심 아이디어입니다. 정지 점은 거리가 충분히 작은 행에서 5 개 이상을 가진 11 점의 주변을 감지하여 발견됩니다. 부울 값의 논리적 배열 내에서 참 값의 가장 긴 하위 시퀀스의 길이를 결정하여이를 좀 더 일반적으로 구현해 보겠습니다.
#
# Return the length of the longest sequence of true values in `x`.
max.subsequence <- function(x) max(diff(c(0, which(!x), length(x)+1)))
(우리는 잘못된 값 의 위치를 순서대로 찾아서 그 차이를 계산합니다. 이는 거짓이 아닌 값의 하위 시퀀스 길이입니다. 이러한 최대 길이가 반환됩니다.)
넷째, max.subsequence
고정 점 감지에 적용 합니다.
#
# Determine whether a point `x` is "stationary" relative to a sequence of its
# neighbors `a`. It is provided there is a sequence of at least `k`
# points in `a` within distance `radius` of `x`, where the earth's radius is
# set to `R`.
is.stationary <- function(x, a, k=floor(length(a)/2), radius=100, R=6378.137)
max.subsequence(dist.array(a, x, R) <= radius) >= k
그것들은 우리가 필요한 모든 도구입니다.
예를 들어, 정지 지점이 몇 군데있는 흥미로운 데이터를 만들어 봅시다. 나는 적도 근처에서 무작위로 걸을 것입니다.
set.seed(17)
n <- 67
theta <- 0:(n-1) / 50 - 1 + rnorm(n, sd=1/2)
rho <- rgamma(n, 2, scale=1/2) * (1 + cos(1:n / n * 6 * pi))
lon <- cumsum(cos(theta) * rho); lat <- cumsum(sin(theta) * rho)
배열 lon
과 lat
의, 각도, 좌표를 포함하는 n
순서 포인트. 라디안으로 변환 한 후에는 도구를 간단하게 적용 할 수 있습니다.
p <- cbind(lon, lat) * pi / 180 # Convert from degrees to radians
p.stationary <- sapply(1:n, function(i)
is.stationary(p[i,], p[max(1,i-5):min(n,i+5), ], k=5))
이 주장 p[max(1,i-5):min(n,i+5), ]
은 기준점에서 5 단계까지, 또는 5 단계만큼 앞뒤로 보인다고 말합니다 p[i,]
. 를 포함하면 k=5
기준점에서 100km 이내에있는 5 개 이상의 시퀀스를 찾습니다. (100km의 값이 기본값으로 설정 is.stationary
되었지만 여기서 무시할 수 있습니다.)
출력 p.stationary
은 정상 성을 나타내는 논리 형 벡터입니다. 그러나 절차를 확인하려면 값 배열을 검사하는 대신 데이터와 이러한 결과를 플로팅하는 것이 가장 좋습니다. 다음 그림에서 경로와 점을 보여줍니다. 10 번째 포인트마다 레이블이 지정되어있어 고정 덩어리 내에서 얼마나 많은 겹칠 지 추정 할 수 있습니다. 고정 점은 빨간색으로 다시 그려져 강조 표시되고 100km 버퍼로 둘러싸여 있습니다.
plot(p, type="l", asp=1, col="Gray",
xlab="Longitude (radians)", ylab="Latitude (radians)")
points(p)
points(p[p.stationary, ], pch=19, col="Red", cex=0.75)
i <- seq(1, n, by=10)
#
# Because we're near the Equator in this example, buffers will be nearly
# circular: approximate them.
disk <- function(x, r, n=32) {
theta <- 1:n / n * 2 * pi
return (t(rbind(cos(theta), sin(theta))*r + x))
}
r <- 100 / 6378.137 # Buffer radius in radians
apply(p[p.stationary, ], 1, function(x)
invisible(polygon(disk(x, r), col="#ff000008", border="#00000040")))
text(p[i,], labels=paste(i), pos=3, offset=1.25, col="Gray")
작업 코드를 포함하여 추적 된 데이터에서 고정 지점을 찾는 다른 (통계 기반) 접근 방식에 대해서는 /mathematica/2711/clustering-of-space-time-data 를 방문 하십시오 .