私は、座標間の距離を表す整数のフラットなリストを作成するために、大きな2D Pythonの浮動小数点リストをループするジェネレータを使用する関数を持っています。Cython - 2次元座標間の距離の配列を計算する
point_input = {"x": -8081441.0, "y": 5685214.0}
output = [-8081441, 5685214]
polyline_input = {"paths" : [[-8081441.0, 5685214.0], [-8081446.0, 5685216.0], [-8081442.0, 5685219.0], [-8081440.0, 5685211.0], [-8081441.0, 5685214.0]]}
output = [[-8081441, 5685214, 5, -2, -4, -3, -2, 8, 1, -3]]
polygon_input = {"rings" : [[-8081441.0, 5685214.0], [-8081446.0, 5685216.0], [-8081442.0, 5685219.0], [-8081440.0, 5685211.0], [-8081441.0, 5685214.0]]}
output = [[-8081441, 5685214, 5, -2, -4, -3, -2, 8, 1, -3]]
純粋なのpython:スピード性能を実現するため
def geometry_to_distance(geometry, geometry_type):
def calculate_distance(coords):
iterator = iter(coords)
previous_x, previous_y = iterator.next()
yield int(previous_x)
yield int(previous_y)
for current_x, current_y in iterator:
yield int(previous_x - current_x)
yield int(previous_y - current_y)
previous_x, previous_y = current_x, current_y
if geometry_type == "POINT":
distance_array = [int(geometry["x"]), int(geometry["y"])]
elif geometry_type == "POLYLINE":
distance_array = [list(calculate_distance(path)) for path in geometry["paths"]]
elif geometry_type == "POLYGON":
distance_array = [list(calculate_distance(ring)) for ring in geometry["rings"]]
else:
raise Exception("{} geometry type not supported".format(geometry_type))
return distance_array
、私は、同じ機能のcython実装を使用します。私はcalculate_distance
関数で整数変数の型宣言を使用しています。
cython実装:ここ
def geometry_to_distance(geometry, geometry_type):
def calculate_distance(coords):
cdef int previous_x, previous_y, current_x, current_y
iterator = iter(coords)
previous_x, previous_y = iterator.next()
yield previous_x
yield previous_y
for current_x, current_y in iterator:
yield previous_x - current_x
yield previous_y - current_y
previous_x, previous_y = current_x, current_y
if geometry_type == "POINT":
distance_array = [geometry["x"], geometry["y"]]
elif geometry_type == "POLYLINE":
distance_array = [list(calculate_distance(path)) for path in geometry["paths"]]
elif geometry_type == "POLYGON":
distance_array = [list(calculate_distance(ring)) for ring in geometry["rings"]]
else:
raise Exception("{} geometry type not supported".format(geometry_type))
return distance_array
機能ベンチマークに使用できるスクリプト:
import time
from functools import wraps
import numpy as np
import geometry_converter as gc
def timethis(func):
'''Decorator that reports the execution time.'''
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end-start)
return result
return wrapper
def prepare_data(featCount, size):
''' Create arrays of polygon geometry (see polygon_input above)'''
input = []
for i in xrange(0, featCount):
polygon = {"rings" : []}
#random x,y coordinates inside a quadrant of the world bounding box in a spherical mercator (epsg:3857) projection
ys = np.random.uniform(-20037507.0,0,size).tolist()
xs = np.random.uniform(0,20037507.0,size).tolist()
polygon["rings"].append(zip(xs,ys))
input.append(polygon)
return input
@timethis
def process_data(data):
output = [gc.esriJson_to_CV(x, "POLYGON") for x in data]
return output
data = prepare_data(100, 100000)
process_data(data)
はcython実装のパフォーマンスを向上させる可能性があり改善がありますか?多分2Dのサイモン配列やカーレーを使って?発電機なしで書き換え
「numpy.diff」を使ってX座標とY座標の1番目の違いを取得するだけではどうですか? – pbreach
巨大な2DのPythonリストからnumpy.arrayを作成するのは遅すぎるようです。 –
cythonやc配列にも同じ問題があります。リストは連続したメモリには格納されず、(均一な)numpy、cython、およびc配列が格納されます。したがって、これらのアプローチに関係なく、変換には時間がかかるでしょう。 'numpy.diff'はジェネレータとリストの使用を考慮してcythonの実装よりも高速ではありません。 – pbreach