4

長さの異なる 2 つの配列があります。1 つは形状の良い多角形を含み、もう 1 つは形状の良い点を含みます。両方の配列の要素の可能な組み合わせごとに a_polygon.contains(a_point) の形の良い関数を実行したいと思います。

この投稿を見ていたのは、可能なすべての組み合わせを行に含む 2 列の行列を構築することが望ましい中間ステップになる可能性があるからです。ただし、「cartersian(arrays)」関数のループは、入力データが巨大な場合にパフォーマンスを低下させる可能性があります。

配列の 1 つをブロードキャストしてから、形状の良い関数を適用しようとしました。

Polygons_array[:,newaxis].contains(Points_array)

もちろん、それはうまくいきません。最近リリースされた geopandas ライブラリを認識していますが、Canopy インストールのオプションではありません。

4

1 に答える 1

5

次のコードは、長さの異なる 2 つの配列に含まれるジオメトリ オブジェクトに関数を適用する方法を示しています。このアプローチでは、ループの使用が回避されます。Pandas の適用と Numpy の .vectorize およびブロードキャスト オプションが必要です。

最初に、いくつかのインポートと次の 2 つの配列を実行することを検討してください。

import numpy as np
import pandas as pd
from shapely.geometry import Polygon, Point

polygons = [[(1,1),(4,3),(4,1),(1,1)],[(2,4),(2,6),(4,6),(4,4),(2,4)],[(8,1),(5,1),(5,4),(8,1)]]
points = [(3,5),(7,3),(7,6),(3,2)]

ポリゴンとポイントのジオメトリ オブジェクトを含む配列は、次のように取得できます。

geo_polygons = pd.DataFrame({'single_column':polygons}).single_column.apply(lambda x: Polygon(x)).values
geo_points = pd.DataFrame({'single_column':points}).single_column.apply(lambda x: Point(x[0], x[1])).values
# As you might noticed, the arrays have different length.

これで、両方の配列に適用される関数が定義され、ベクトル化されました。

def contains(a_polygon, a_point):
    return a_polygon.contains(a_point)
contains_vectorized = np.vectorize(contains)

このようにして、関数はベクトル内のすべての要素に適用されるように準備されます。ポイント配列をブロードキャストすると、ペアごとの評価が処理されます。

contains_vectorized(geo_polygons, geo_points[:,np.newaxis])

次の配列を返します。

array([[False,  True, False],
   [False, False, False],
   [False, False, False],
   [ True, False, False]], dtype=bool)

列はポリゴンに対応し、行はポイントに対応します。その配列のブール値は、たとえば、最初のポイントが 2 番目のポリゴン内にあることを示します。どちらでも構いません。ポリゴンとポイントをマッピングすると、それが正しいことが証明されます。

from descartes import PolygonPatch
import matplotlib.pyplot as plt
fig = plt.figure(1, figsize = [10,10], dpi = 300)
ax = fig.add_subplot(111)
offset_x = lambda xy: (xy[0] + 0.1, xy[1])
offset_y = lambda xy: (xy[0], xy[1] - 0.5)
for i,j in enumerate(geo_polygons):
    ax.add_patch(PolygonPatch(j, alpha=0.5))
    plt.annotate('polygon {}'.format(i + 1), xy= offset_y(tuple(j.centroid.coords[0])))
for i,j in enumerate(geo_points):
    ax.add_patch(PolygonPatch(j.buffer(0.07),fc='orange',ec='black'))
    plt.annotate('point {}'.format(i + 1), xy= offset_x(tuple(j.coords[0])))
ax.set_xlim(0, 9)
ax.set_ylim(0, 7)
ax.set_aspect(1)
plt.show()

マッピングされたジオメトリ

于 2014-07-24T16:21:39.843 に答える