空間と時間の近接


10

タイムスタンプが関連付けられた、動物の毎日の緯度の場所を表すいくつかのポイントデータがあります。

STATIONARY = TRUEであるすべてのポイントを特定したいと思います。ポイントの周囲の100kmのバッファーが時間的に隣接する追加の(たとえば)5つの ポイントと重なる場合、そのポイントは静止していると見なされます。したがって、10日目が私の興味のあるポイントである場合、時間的に隣接する5日がこのポイントから100 kmのバッファー内にあるかどうかを確認したいと思います。5、6、7、8、9日の場合。または11、12、13、14、15日。または8、9、11、12、13日などがバッファー内にあり、その後STATIONARY = TRUE。ただし、5、7、9、11および13日がバッファー内にあり、その間の隔日(偶数)ではない場合、STATIONARY = FALSE

何らかの移動ウィンドウバッファーが解決策を提供すると思いますが、これを実装する方法がわかりません。

私はArcGISとRの両方でこの問題を回避しようと努めてきましたが、今のところ脳波はありません。これは私がソリューションに持っている最も近いものですが、それは完全には適合しません、私は思いません:指定されたバッファー内の連続したポイントの識別

これは、データ構造を近似するいくつかのダミーデータです(実際には、1日2回(正午と真夜中)の場所があり、いくつかの場所が欠落していますが、後で心配します)。

x<-seq(0,15,length.out=20)
y<-seq(10,-10,length.out=20)
t<-seq(as.POSIXct('2013-07-01'), length.out = 20, by = "days")
data<-data.frame(cbind(x,y,t=as.data.frame.POSIXct(t)))


            x           y          t
1   0.0000000  10.0000000 2013-07-01
2   0.7894737   8.9473684 2013-07-02
3   1.5789474   7.8947368 2013-07-03
4   2.3684211   6.8421053 2013-07-04
5   3.1578947   5.7894737 2013-07-05
6   3.9473684   4.7368421 2013-07-06
7   4.7368421   3.6842105 2013-07-07
... ...         ...       ...

1
質問?10ポイントすべてがバッファー内にあり、日付の分離(1日目から開始)が1-3-4-12-13-20-21-22-29-30であるとすると、ポイントの選択のみに関心があると言いますかそれは1、2、3、4、12日目ですか?
Hornbydd 2013

いいえ、関心があるのは1〜4日目だけです。動物がバッファーを「離れる」場合、12日目(または6日目)に戻ると、その静止期間が「キャンセル」されます。つまり、動物は1-2-3-4-5日の間バッファーにいる必要がありますカウントするバッファの中心のポイント。理にかなっていますか?私は確かに自分自身...ないんだけど
トム・フィンチ

1
チェックするだけで、関心のあるポイントが7日目である場合、7、8、9、10、11日目に100Km以内にある関心のあるポイントですか?
Hornbydd

8日目、9日目、10日目、11日目、12日目が100 kmを超えている場合、ポイント7が静止ポイントとして選択されます。または、5、6、8、9、10日。したがって、時間的に隣接する他の5つのポイント(前の5日間、次の5日間、または両側の数日)がすべてバッファー内にある場合、任意の1つのポイントが選択されます。移動ウィンドウはそれを概念化する最良の方法だと思います。「フォーカル」ポイントごとに、過去/未来から5日以上経過したポイントはすべて忘れられます。もう少し理解できるようになったので、元の質問を更新します...
Tom Finch

データの形式は何ですか?たとえば、シェープファイルのベクトルポイントとして各時間/場所と、時間を格納する属性テーブルがありますか?または、それぞれの時間/場所が異なるシェープファイルに個別に保存されていますか?データは地理空間形式ではなく、単にExcelファイルにありますか?これを知ることは私たちが答えるのに役立ちます。

回答:


12

これを簡単な部分に分解してみましょう。そうすることで、すべての作業は簡単にテストできるわずか数行のコードで実行されます。

まず、距離を計算する必要があります。データは地理座標系にあるため、球面データムの距離を計算する関数があります(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, ...))

3つ目は、これが重要なアイデアです。静止した点は、距離が十分に小さい行に少なくとも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)))

誤った値の場所を順番に見つけて、それらの違いを計算します。これらは、誤った値ではないサブシーケンスの長さです。そのような最大の長さが返されます。)

第4に、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)

配列lonlatは、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と、基点から100 km以内にある5つ以上のシーケンスを連続して検索します。(デフォルトでは100 kmの値が設定されてis.stationaryいますが、ここでオーバーライドできます。)

出力p.stationaryは、定常性を示す論理ベクトルです。ただし、手順を確認するには、値の配列を検査するのではなく、データとこれらの結果をプロットするのが最善です。次のプロットでは、ルートとポイントを示しています。10個ごとのポイントにラベルが付けられるので、静止した束内で重複する可能性のある数を推定できます。静止ポイントは赤く塗りつぶされて強調表示され、100 kmのバッファーで囲まれます。

図

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")

作業コードを含む、追跡されたデータで静止点を見つける他の(統計ベースの)アプローチについては、https://mathematica.stackexchange.com/questions/2711/clustering-of-space-time-dataにアクセスしてください


わあ、ありがとう!これに頭を悩ませることを楽しみにしています。あなたの時間と労力のためにもう一度感謝
トム・フィンチ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.