Python:条件に基づいてラインストリングを分割


11

各頂点/ポイントに関連付けられたいくつかのデータを持つ一連のラインストリングのジオパンダデータフレームがあります。

Point_x = (Lat, Lon, Time, ID, Data1, Data2, Data3)

ポイントは、IDに基づいてラインストリングに変換され、時間順に並べられます。

ある条件が満たされた時点で、ラインストリングを分割したい。現在、ポイント間の距離が特定の値よりも大きい場合です。将来的には、データフィールドの機能が何らかの値になる可能性があります。たとえば、速度が5 kphを超えるとラインストリングを分割します。

現在の問題は、トラックの一部が重複したIDを持つポイントから形成されているため、ラインストリングが非常に長い距離で前後にジャンプし、これらのラインを分割するためのしきい値が必要なことです。

これまたはライブラリ/メソッドを構造化する正しい方法に関するアイデアはありますか?

データフレームには15,000を超えるトラックがあり、トラックごとに多くのポイントが含まれているため、効率が良いでしょう。

トラックDFの例を次に示します。

ID         geometry                                                  
204235000  LINESTRING (37.62001 -28.99535, 37.62015 -28.9...   
205400000  LINESTRING (3.807816666666666 -18.083181666666...   
207138000  LINESTRING (22.73206 -34.97915833333333, 22.73...   
209016000  LINESTRING (8.447673333333331 -23.522783333333...     

これがポイントDFのサンプルです。Datetime、Point(Lon、Lat)、Speed、Sizeなどを含む18列があります。

Index           Heading   Latitude  Longitude       ID  
20              92.8 -35.946802  13.089695  210725000               
21              93.5 -35.946912  13.091808  210725000               
22              95.4 -35.965520  13.497698  210725000               
23              94.7 -35.965803  13.501898  210725000               
24              94.9 -35.965987  13.504573  210725000               

編集:少し明確にしようとしました。


GeoDataFrameの構造は何ですか?のコピーをgd.head()歓迎します。
遺伝子

頭を表示するように編集
RedM

過去に似たようなことをするためにGeoPy(geopy.distance.vincenty)を使用しました。ポイントを接続する必要がありましたが、決められたしきい値よりも長い場合は接続しません。関数を介して座標の各ペアを送信し、しきい値よりも小さい場合にのみ接続しました。geopy.readthedocs.io/en/1.10.0/#geopy.distance.vincenty
JohnR

重複ID機能の主キー/ソート条件は何ですか?時間対IDまたはID対時間ですか?
ハックフィン

どういう意味か本当にわかりません。ポイントはIDでグループ化され、次に時間で並べ替えられ、次に順序付けられた位置が線ストリングの作成に使用されます。IDはオブジェクト間で重複する場合があります。例:ID = '123'の都市Aに車があります。位置と時間を送信しています。また、都市BにはID = '123'の車があり、その位置も送信しており、時間はインターリーブされています。これらのポイントから構築されたラインは、AとBの間をジャンプします
RedM

回答:


1

まだshapely / geopandasを使用していないので、擬似コードのみを提供できます。

distance_threshold = 50 # Value at which distance to cut off
new_lines = [] # Array to hold the newly created, split lines
new_line_marker = 0 # Let's remember where our new line starts
for linestring in linestrings: # Iterate over all linestrings
  for i, coord in enumerate(linestring.coords[:-1]): # Iterate over all coords of the linestring
    if distance(coord, coords[i+1]) >= distance_threshold: # Check if threshold is met
      # If condition is met, we generate a new linestring,
      # starting from the last split to the current one
      new_lines[] = new LineString(coords[new_line_marker:i])
      new_line_marker = i+1 # remember to reset the marker

距離関数は、ライブラリが既に提供しているものであるか、自分で実装する必要があります(相棒のピタゴラスがお手伝いします)。

そこから必要に応じて効率を改善できますが、それは良い出発点になるはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.