大きなテーブルを持つPythonでArcGISカーソルを使用するときにパフォーマンスを向上させる方法は?


10

ファイルジオデータベースにかなり大きなポイントフィーチャクラスがあります(最大4 000 000レコード)。これは、100mの解像度を持つ通常の点のグリッドです。

このレイヤーで一種の一般化を行う必要があります。このために、各ポイントが4つの「古い」ポイントの中央にある新しいグリッドを作成します。

 *     *     *     *
    o     o     o
 *     *     *     *
    o     o     o
 *     *     *     *

[*] =元のグリッドのポイント-[o] =新しいグリッドのポイント

新しい各ポイントの属性値は、古いグリッドの4つの近傍の重み付けされた値に基づいて計算されます。したがって、新しいグリッドのすべてのポイントでループし、それらのそれぞれについて、(属性テーブルのXとYの値を比較することによって)隣人を見つけるために、古いグリッドのすべてのポイントでループします。4つのネイバーが見つかったら、ループから抜け出します。

ここには方法論的な複雑さはありませんが、私の問題は、私の最初のテストに基づいて、このスクリプトが完了するまで数週間続くことです...

それをより効率的にする可能性はありますか?私の頭の上のいくつかのアイデア:

  • フィールドXとYにインデックスを付ける=>私はそうしましたが、大きなパフォーマンスの変化に気づきませんでした
  • 属性ベースのクエリではなく、空間クエリを実行して近傍を検索します。それは実際に役立ちますか?ArcGISのどの空間関数がその仕事をするべきですか?たとえば、新しい各ポイントをバッファリングすることがより効率的であるとは思えない
  • フィーチャクラスをNumPy配列に変換します。それは役に立ちますか?私はこれまでNumPyをあまり使用していないので、誰かが処理時間を短縮するのに本当に役立つと私に言わない限り、それについて詳しく知りたくありません。
  • 他に何か?

使用しているArcmapのバージョンは何ですか?
マーティン

PostGISを検討しましたか?それはオプションですか?
チャドクーパー

申し訳ありませんが、私は忘れてしまったことをその:ArcGISの10.1 // Pythonの2.7
ステファンHenriod

いや、PostGISには、残念ながら私はSDE機能でOracleを使用することができる最高で、私の手が、残念ながらかなり...ここに結び付けられているオプションではありません
ステファンHenriod

回答:


13

ポイントをnumpy配列に入力し、scipy cKDTreeを使用して近傍を検索するとどうなるでしょうか。この手法を使用して、数分でLiDAR点群を多数のポイント(> 2,000万)で処理します。ドキュメントがあり、ここで kdtreeのためにと、ここで numpyの変換のために。基本的に、x、yを配列に読み取り、配列内の各ポイントを反復処理して、各ポイントの特定の距離(近隣)内のポイントのインデックスを見つけます。これらのインデックスを使用して、他の属性を計算できます。


この回答は私のものより優れています
radouxju 2014年

このアイデアは好きですが、作業しているワークステーションにScipyがありません(管理者権限がありません)。私は、このパッケージがインストールされて取得する管理している場合、私はそれを試してみるよ
ステファンHenriod

4

私はバルバロッサと一緒にいます... arcpyカーソルはめちゃくちゃ足りないので、テーブルまたはフィーチャクラスを1回だけトラバースするためにのみ使用します。1サイクルでジョブを完了できない場合は、カーソルを使用して他の種類のデータ構造を埋め、それを処理します。

numpyに煩わされたくない場合は、座標を単純なテキストキーとして使用する単純なpython 辞書を作成し、計算に必要な属性を辞書項目の値としてリストに入力します。

2番目のステップでは、ディクショナリから取得するだけで、ポイントを計算するために必要な値を簡単に取得できます(アイテムのディクショナリハッシュインデックスのため、非常に高速です)。


私は実際、辞書を使ったあなたのアイデアが好きで、実装しました。実際にはるかにうまく機能します...実際にrow.insertRow()で結果を書き込むまで...この部分もどのように改善できるかについてのアイデアはありますか?
ステファンHenriod

同様の問題があり、14 Mioから10.000ポイントを選択する必要がありました。それを削除します。1秒あたり約1または2ポイント(!)しか削除できないarcpy.cursors。pyodbcモジュールをインストールして、1つのSQL DELETEステートメントで1秒で削除するようにしました。SQLを介してUPDTATEを実行すると、属性のみを変更する必要がある場合に限り、多くの改善がもたらされます。それでも、追加のpythonモジュールをインストールする必要がありますが、その価値はあります。
ユルゲン・Zornig

2

通常のグリッドでは、ラスター形式で作業する方がはるかに効率的です。最初のグリッドをラスターに変換します。双線形補間を使用して同じ解像度でリサンプリングできますが、出力画像をXとYで1/2ピクセルシフトし、ポイントが必要な場合はポイントに戻します。

編集:複雑な決定ルールの場合、必要な各フィールドを新しいラスターバンドとして変換し、それらのバンドの4つのコピーを作成して、ラスターを4方向に1/2ピクセル(+50、- 50)、(+ 50、+ 50)、(-50、-50)、(-50、+ 50)。次に、通常のマップ代数を使用できます


ありがとう、私は実際にこのソリューションを考えましたが、ラスター形式の場合に新しい値の計算を実装できるかどうか、またはどのように実装できるかわかりません。説明させてください:新しいポイント(または新しいラスターセル)ごとに、その値を計算する必要があります。その近傍のそれぞれの値を取ります。これらの値のそれぞれは、新しいポイントに特定の値を与える可能性があります。たとえば、1つのネイバーの値が202の場合、値3(重み1)または値11(重み5)になります。私たちはその後、わからない、これは非常に明確であるかどうか... ...すべての4人の隣人のための総括と新たな価値を見出す
ステファンHenriod

PS:新しい価値を見つけるための計算は、いくつかのケースでは、ラスターアプローチを捨てるかもしれない2つの属性は、1つだけでなく、に基づくことができる
ステファンHenriod

重み付けされた合計の場合、2つのラスターが必要です。1つは重みと値の積をリサンプリングし、もう1つは重みのみをリサンプリングします。最初の値を2番目の値で割ると、加重和が得られます。
radouxju 2014年

1
@StéphaneHenriod-提案として、質問を編集してこれらの追加の仕様を追加することを検討できます。最初の質問を考えると、この回答は非常に理にかなっていると思いますが、この新しい情報があれば、バルバロッサの回答は良さそうです。
Nicksan 2014年

2

皆さん、助けてくれてありがとう!

私はようやくこの問題を解決するための非常に非Python的な方法を見つけました...実際に最も計算時間を費やしていたのは、各ポイントの4つの近傍を見つけることでした。X属性とY属性を使用するのではなく(arcpyカーソルを使用するか、Python辞書などの別のデータ構造内で)、ArcGISツールのGenerate near tableを使用しました。これは空間インデックスを利用しており、自分でインデックスを実装する必要がないため、パフォーマンスは明らかにはるかに高いと思います。


0

カーソルの問題は、カーソルを一方向にしか循環できず、戻ることができないことです。お勧めしませんが、機能を再検討する場合は、機能に構造を設定できます。

機能を1つのループで処理できた場合は、リサイクルを有効にすることをお勧めします。これは、検索機能クラス関数のパラメーターであり、Pythonが古い機能によって割り当てられたメモリを再利用し、カーソル内の機能をはるかに高速に移動できるようにします。グリッドを80%速く処理できます。

問題は、カーソルから取得したフィーチャーを保存することを計画している場合、リサイクルを有効にできないことです。


この「リサイクルカーソル」のテーマを調べたいのですが、ESRIヘルプのドキュメントが見つかりません。リンクはありますか?検索カーソルにはリサイクルパラメータはありません。Select_by_Attributeにはそのようなパラメーターはありません。ENVには何も表示されません。
クレウィス2014年

私はしばらく前に記事を書いたhusseinnasser.com/2009/08/when-to-use-recycling-cursor.html?m=1
hnasr

1
「カーソルの再利用」は、コアのArcobjectsでのみ、ArcPyを通じて利用できるとは思いません。
クレウィス2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.