2016-06-24 12 views
0

ポイントと複数の線分の間の測地線距離を計算しています。各線分には固有の識別番号があります。私は距離関数から距離を戻したいので、それらは本質的に一緒に結びついています。また、距離をソートする際のように機能を維持し、ラベルまたは位置のいずれかを使用してインデックスを作成し、距離データとラベルの両方を取得したいと考えています。インデックスを持つパンダシリーズのようなものですが、データがパンダのDataFrameに返されるため、シリーズを使用できません。その結果、シリーズが展開され、混乱します。私はしかし、ラベルとの距離は、本質的に相互に関連付けられています。この辞書のようなものである必要は何ラベル付きデータ型Python

In [1]: '''Note that all this happens inside an apply function of a Pandas Series''' 
     labels = [25622, 25621, 25620, 25619, 25618] 
     dist = vect_dist_funct(pt, labels) #vect_dist_funct does the computations, and returns distances in meters 
     dist 
Out[1]: array([296780.2217658355, 296572.4476883276, 296364.21166884096, 
       296156.4366241771, 295948.6610171968], dtype=object) 

:ここでは一例である

{25622 : 296780.2217658355, 
25621 : 296572.4476883276, 
25620 : 296364.21166884096, 
25619 : 296156.4366241771, 
25618 : 295948.6610171968} 

しかし、今、私はの機能を失っています値。私は簡単にそれらを並べ替えることはできません、またはそれらを比較するか、何か。私はNumpy Structured Arraysを見ましたが、それは実行可能なように見えますが、私が距離を並べ替えることができず、最も近いセグメントのインデックスを得ることができない場合、それは私にあまり役に立たないでしょう。私が使用できる他のデータ型はありますか?

ロングストーリーや背景

私が参加した空間をやろうとしています。私はRTree(example)で検索することによって、ポイントが最も近い可能性のあるセグメントのインデックスを取得します。それらはラベルのインデックスです。次に、線の幾何学的な表を見て、選択したラベルの線のジオメトリを見つけ、各線分の点の距離を計算します。

次の手順には、空間結合の健全性チェックが必要です。最も近いものが最良の結合候補ではない場合があり、結合を他のパラメータで評価する必要があります。したがって、私の計画は最も近いセグメントから外側に向かって作業することです。距離をソートし、最も近いセグメントのインデックスを取得し、次にそのインデックスを持つセグメントテーブルを調べ、検査のためにラインの他のプロパティを抽出する。一致が確認できれば、前記セグメントは受け入れられ、そうでなければ拒否され、アルゴリズムは次に近いセグメントに移動する。

これをすべて行うデータ型は、計算されたセグメントの距離の間のリンクを壊すことなく、私が探しているデータ型です。

joined = points['geometry'].apply(pointer, centroid=line['centroid'], tree_idx=tree_idx)) 

その後pointerの内側に、この問題が発生した:その後、

def pointer(point, centroid, tree_idx): 
    intersect = list(tree_idx.intersection(point.bounds)) 
    if len(intersect) > 0: 
     points = pd.Series([point.coords[0]]*len(intersect)).values 
     polygons = centroid.loc[intersect].values 
     dist = vect_dist_funct(points, polygons) 
     return pd.Series(dist, index=intercept, name='Dist').sort_values() 
    else: 
     return pd.Series(np.nan, index=[0], name='Dist') 

そして、joined

パンダ使用して

問題は、これは関数が実際に呼び出されている方法です次のようになります。

There is no point in copying the table, I guess.

これは、すべての点(行がポイント)とすべてのライン(列がライン)の間の距離が計算されないためです。それはあまりにもコストがかかりすぎるであろう(4Mポイント、州当たり180kライン、データセット全体で50州)。また、このDataFrameマージ操作で生成されたjoinedは、2つのNumpy配列を返す場合と比較して、実行時間が7倍に増加します。 2つのNumpy配列を返す問題は、距離と行IDを常に整列させることは容易ではないということです。ポイント、ラインの

例には、これは列と行に切り捨てデータセットであることを

注tree_idx。私は唯一の関連性の列ではなく、残りのデータを含めています:

ポイント:

     geometry 
id  
88400001394219 0.00 POINT (-105.2363291 39.6988139) 
       0.25 POINT (-105.2372017334178 39.69899060448157) 
       0.50 POINT (-105.2380177896182 39.69933953105642) 
       0.75 POINT (-105.2387202141595 39.69988447162143) 
       1.00 POINT (-105.2393222 39.7005405) 
88400002400701 0.00 POINT (-104.7102833 39.8318348) 
       0.25 POINT (-104.7102827 39.831966625) 
       0.50 POINT (-104.7102821 39.83209845) 
       0.75 POINT (-104.7102815 39.832230275) 
       1.00 POINT (-104.7102809 39.8323621) 

だから、これは基本的にライン上の補間点です。行IDはインデックスの第1レベルであり、第2レベルはポイントが補間されたパーセントです。これは、最初のデータセット、つまり2番目のデータセットからいくつかの属性を取り込むデータセットを形成します。

ライン:

 geometry           centroid 
id  
71345 POLYGON ((-103.2077992965318 40.58026765162965... (-103.20073265160862, 40.576450381964975) 
71346 POLYGON ((-103.2069505830457 40.58155121711739... (-103.19987394433825, 40.57774903464972) 
71347 POLYGON ((-103.2061017677045 40.58283487609803... (-103.19901204453959, 40.57905245493993) 
71348 POLYGON ((-103.2052000154291 40.58419853220472... (-103.19815200508097, 40.58035300329024) 
71349 POLYGON ((-103.2043512639656 40.58548197865339... (-103.19729445792181, 40.58164972491414) 
71350 POLYGON ((-103.2035025651746 40.5867652936463,... (-103.1964362470977, 40.5829473948391) 
71351 POLYGON ((-103.2026535431035 40.58804903349249... (-103.19557847342394, 40.58424434094705) 
71352 POLYGON ((-103.201804801526 40.58933229190573,... (-103.19472966696722, 40.58552767098465) 
71353 POLYGON ((-103.2009557884142 40.59061590473365... (-103.19388484652855, 40.58680427447224) 
71354 POLYGON ((-103.2001001699726 40.59190793446012... (-103.19303392095904, 40.5880882237994) 

これが第二のデータセットの一部である(この答えの冒頭で言及したラベルは、このデータセットの指標です)。目標は、このデータセットの属性をポイントデータセットにインテリジェントに転送することです。最初のステップは、各点に最も近い線を見つけることです。次に、ポイントデータセットの属性をラインデータセットと比較し、私が言及したように結合を確認または拒否します。

tree_idx:tree_idxは、次のコードを使用して作成され

:だから

import rtree 
lines_bounds = lines['geometry'].apply(lambda x: x.bounds) 
tree_idx = rtree.index.Index() 
for i in lines_bounds.index: 
    tree_idx.insert(i, lines_bounds.loc[i]) 
+0

あなたが持っているが辞書では達成できない機能について詳しく説明できますか? –

+0

私は空間結合をしようとしています。そして、そうすることで、最も近いものが必ずしも正しい結合パートナーとは限りません。結合を確認する前に調べる必要がある他のパラメータがあります。だから私の計画は、私が行くように、最も外側からチェックし、確認したり拒否したりすることです。辞書は構造化されておらず、ソートされて保存することはできません。また、辞書は位置によってインデックス可能ではなく、手前のすべてのセグメントのキーを知ることはできません。 – Kartik

+1

あなたのケースでパンダシリーズ/ DataFrameを使用できない理由を説明できますか?パンダは正確に説明したものです(値とラベルの間のリンクを維持していますが、まだ値を使用して並べ替えることができます) – joris

答えて

1

だから私はあなたの全体的な問題はDataFrameを作成していると思います。ここで列ラベルはinterceptの値です。あなたがしたいことは、DataFrameを作成することであると考えています。ここで、ある列はインターセプト値を含み、別の列は距離を含みます。私はあなたに役立つだろうと思うコードを提供しようとしますが、元のデータを持たないと特定するのは難しいので、完全に機能するには多少変更する必要があります。

最初に、最初の引数がスカラーの場合は正しい長さのリストを作成し、2番目の値が空の場合はNaNを返します。

次は私がDATAFRAMEに列として、すべての有用な値を追加します。

points['intersect'] = points['geometry'].apply(lambda x: np.array(tree_idx.intersection(x.bounds))) 
points['polygons'] = points['intersect'].apply(lambda x: centroid.loc[x].values) 
points['coords0'] = points['geometry'].apply(lambda x: x.coords[0]) 
points['dist'] = points.apply(lambda x: vect_dist_funct(x.coords0, x.polygons), axis=1) 

これはその中のすべての距離であなたのコラムを与えるだろう。あなたが本当にインターセプト値がアクセスできるようにしたい場合は、その後、ちょうどインターセプトと距離とのDataFrameを作成し、あまりにも多くのNaN値を避けるために、別のマルチインデックスレベルとしてインターセプトを置くことができます。

pairs = points.apply(lambda x: pd.DataFrame([x['intersect'], x['dist']], index=['intersect', 'dist']).T.stack(), axis=1) 
pairs = pairs.stack(level=0).set_index('intersect', append=True) 
pairs.index = pairs.index.droplevel(level=2) 

これは与えるべきですあなたはSeriesです。最初のインデックスはid、2番目はパーセント、3番目は交差、そして値は距離です。

+0

名誉!これはありがとうございます!それはいくつかの "ああ - ハ"を引き起こし、2つの額を叩く結果になった。私はあまりにも巻き込まれてしまったので、そこにはまった。 – Kartik

+0

あなたの答えを実装したところ、かなりの問題があることが判明しました。まず、 'tree_idx.intersection'がジェネレータを与えます。しかし、これは 'centroid.loc [list(x)]'を使って簡単に修正できました。そして、これはいくつかの場所でリストを返すので、距離計算はそれほど簡単ではありません。私はまだそれを行う方法を理解するために働いています... – Kartik

+0

任意のアイデア@TheBlackCat?問題は 'points ['coords0']'はx座標とy座標のタプルを持つということです。しかし、 'points ['polygons']'はx座標とy座標を含むタプルのリストです。このリストの長さは、0から151の間の任意の長さにすることができます。したがって、基本的には、 'points' DataFrameのすべての行について、 'coords0'を 'polygons'と同じくらい長く繰り返し、このリストの各要素について計算した距離を計算する必要があります。 – Kartik

0

を、私はそのインデックスラベルであるデータフレームは、おそらく最も簡単な

distances = {25622 : 296780.2217658355, 
25621 : 296572.4476883276, 
25620 : 296364.21166884096, 
25619 : 296156.4366241771, 
25618 : 295948.6610171968} 

df = pd.DataFrame([tup for tup in distances.items()],columns=["label", "dist"]).sort_values('dist').set_index('label') 
df 

出力するようになっていると思います:

dist 
label 
25618 295948.661017 
25619 296156.436624 
25620 296364.211669 
25621 296572.447688 
25622 296780.221766 

そして、あなたはラベル名で

df.loc[25620] 
Out: 
dist 296364.211669 
Name: 25620, dtype: float64 

そして、あなたは、ラベル「近く」そのポイントを検索したい場合は、その後、あなたは

row_num = df.index.get_loc(25620) 
print(row_num) 
Out: 2 

と行番号を取得することができますが、距離にアクセスする場合とそして、あなたが必要なすべてを網羅df.iloc[row_number]

df.iloc[3] 
Out: 
dist 296572.447688 
Name: 25621, dtype: float64 

んで「近い」のポイントにアクセスすることができますか?

+0

いいえ、Series/DataFrameを返すと、全体が多くのNaN値に展開されるためです。呼び出し元の関数はGeoDataFrameに適用されるため、戻り値の型が別のPandas Seriesである場合、それが出力に結合され、プロセス全体が長くなりすぎます。 – Kartik

+0

あなたの質問から、あなたのデータを '{key:value} 'のペアにすることができると思いましたが、そうではありませんか? –

+0

このソリューションは簡単にソート可能で簡単に比較可能で、ラベルとその距離の関係を維持しながら、近くのラベルを簡単に見つける機能を維持します。それはあなたが求めているのはどういうことでしょうか? –

0

約3時間TheBlackCatの回答を作ろうとした後、私はxarrayを使用することに決めました。だから今度はpointer関数は次のようになります:

def pointer(point, centroid, tree_idx): 
    intersect = list(tree_idx.intersection(point.bounds)) 
    if len(intersect) > 0: 
     points = pd.Series([point.coords[0]]*len(intersect)).values 
     polygons = centroid.loc[intersect].values 
     dist = vect_dist_funct(points, polygons) 
     sorter = np.argsort(dist) 
     return xr.DataArray(dist[sorter], [('dim0', np.asarray(intersect)[sorter])]) 
    else: 
     return xr.DataArray(np.nan) 

完了しました。これは私の必要に応えます。私は、それらが一緒に計算された距離とセグメントIDを持っているので、一方の変換は他方のものに影響します。そして、距離はまだ動作可能であり、xarrayは、グループ化、マージなどの点で高度な機能も提供します。

また、これは状態のデータの0.1%を実行するのに約1分かかります。データの10%。したがって、私は100%のデータが約100分であると予想しています。しかし、正直言って、ある州では3時間かかっても、1日で50州すべてを終了することができます(16コアサーバーでのマルチスレッドを使用)。だから私は当分これで満足しています。私が得たすべての提案に感謝します。特に@TheBlackCat、@michael_j_ward、@ hpaulj。

関連する問題