1

浮動小数点数の 2 つのリストがあり、それらの間の集合の差を計算したいと考えています。

numpy を使用して、最初に次のコードを作成しました。

aprows = allpoints.view([('',allpoints.dtype)]*allpoints.shape[1])
rprows = toberemovedpoints.view([('',toberemovedpoints.dtype)]*toberemovedpoints.shape[1])
diff = setdiff1d(aprows, rprows).view(allpoints.dtype).reshape(-1, 2)

これは、整数などに適しています。いくつかの幾何学的計算の結果である float 座標を持つ 2d ポイントの場合、有限の精度と丸め誤差の問題があり、集合の差がいくつかの等式を見逃す原因となります。今のところ、私ははるかに遅いことに頼りました:

diff = []
for a in allpoints: 
    remove = False
    for p in toberemovedpoints:
        if norm(p-a) < 0.1:
            remove = True
    if not remove:
        diff.append(a)
return array(diff)

しかし、これを numpy で記述して速度を戻す方法はありますか?

残りのポイントにはまだ完全な精度を持たせたいので、最初に数値を丸め、次に設定差を行うことはおそらく先に進む方法ではないことに注意してください(またはそうですか?:))

動作するように見える scipy.KDTree に基づくソリューションを追加するように編集しました:

def remove_points_fast(allpoints, toberemovedpoints):
    diff = []
    removed = 0
    # prepare a KDTree
    from scipy.spatial import KDTree
    tree = KDTree(toberemovedpoints,  leafsize=allpoints.shape[0]+1)
    for p in allpoints:
        distance, ndx = tree.query([p], k=1)
        if distance < 0.1:
            removed += 1
        else:
            diff.append(p)
    return array(diff), removed
4

1 に答える 1

1

これを行列形式で行う場合、配列が大きくなると大量のメモリが消費されます。それが問題にならない場合は、次の方法で差分行列を取得します。

diff_array = allpoints[:,None] - toberemovedpoints[None,:]

結果の配列には、allpoints のポイントと同じ数の行と、tobemovedpoints のポイントと同じ数の列があります。次に、これを任意の方法で操作できます (たとえば、絶対値を計算する)。これにより、ブール配列が得られます。ヒットした行 (絶対差 < .1) を見つけるには、次を使用しますnumpy.any

hits = numpy.any(numpy.abs(diff_array) < .1, axis=1)

これで、差分配列に行があったのと同じ数の項目を持つベクトルができました。そのベクトルを使用して、すべてのポイントにインデックスを付けることができます (一致しないポイントが必要だったため、否定)。

return allpoints[-hits]

これは、これを行うための厄介な方法です。ただし、上で述べたように、大量のメモリが必要です。


より大きなデータがある場合は、ポイントごとに実行することをお勧めします。このようなもの:

return allpoints[-numpy.array([numpy.any(numpy.abs(a-toberemoved) < .1) for a in allpoints ])]

これはほとんどの場合うまく機能し、メモリ使用量はマトリックス ソリューションよりもはるかに少なくなります。(文体上の理由から、numpy.any の代わりに numpy.all を使用し、比較を逆にして否定を取り除くことができます。)

(コードに印刷ミスがあるかもしれないことに注意してください。)

于 2014-06-15T21:17:18.750 に答える