python - 将重复参数传递给 Numpy 向量化函数的最佳方法

标签 python numpy optimization geopy

所以,继续@TheBlackCat 和我在 this answer 中的讨论,我想知道将参数传递给 Numpy 向量化函数的最佳方法。所讨论的函数是这样定义的:

vect_dist_funct = np.vectorize(lambda p1, p2: vincenty(p1, p2).meters)

其中,vincenty 来自 Geopy package .

我目前以这种方式调用 vect_dist_funct:

def pointer(point, centroid, tree_idx):
    intersect = list(tree_idx.intersection(point))
    if len(intersect) > 0:
        points = pd.Series([point]*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')

points['geometry'].apply(lambda x: pointer(point=x.coords[0], centroid=line['centroid'], tree_idx=tree_idx))

(问题请引用这里:Labelled datatypes Python)

我的问题与函数 pointer 内部发生的事情有关。我将 points 转换为 pandas.Series 然后获取值(在第 4 行,就在 if 语句下方)的原因是使其与多边形形状相同。如果我只是将点称为 points = [point]*len(intersect)points = itertools.repeat(point, len(intersect)),Numpy 会提示它“不能同时广播大小为 (n,2) 和大小为 (n,) 的数组”(n 是 intersect 的长度)。

如果我像这样调用 vect_dist_funct:dist = vect_dist_funct(itertools.repeat(points, len(intersect)), polygons), vincenty 提示我给它传递了太多论据。我完全无法理解两者之间的区别。

请注意,这些是坐标,因此总是成对出现。以下是多边形 的示例:

point = (-104.950752   39.854744) # Passed directly to the function like this.
polygons = array([(-104.21750802451864, 37.84052458697633),
                  (-105.01017084789603, 39.82012158954065),
                  (-105.03965315742742, 40.669867471420886),
                  (-104.90353460825702, 39.837631505433706),
                  (-104.8650601872832, 39.870796282334744)], dtype=object)
           # As returned by statement centroid.loc[intersect].values

在这种情况下调用 vect_dist_funct 的最佳方法是什么,这样我就可以进行矢量化调用,并且 Numpy 和 vincenty 都不会提示我传递了错误的参数?此外,还寻求导致最小内存消耗和增加速度的技术。目标是计算点到每个多边形质心之间的距离。

最佳答案

np.vectorize 在这里并不能真正帮助您。根据 documentation :

The vectorize function is provided primarily for convenience, not for performance. The implementation is essentially a for loop.

事实上,vectorize 会主动伤害您,因为它将输入转换为 numpy 数组,进行不必要且昂贵的类型转换并产生您所看到的错误。您最好使用带有 for 循环的函数。

对于层级函数,最好使用函数而不是 lambda,因为它可以让您拥有文档字符串。

这就是我将如何实现您正在做的事情:

def vect_dist_funct(p1, p2):
    """Apply `vincenty` to `p1` and each element of `p2`.

    Iterate over `p2`, returning `vincenty` with the first argument
    as `p1` and the second as the current element of `p2`.  Returns
    a numpy array where each row is the result of the `vincenty` function
    call for the corresponding element of `p2`.
    """
    return [vincenty(p1, p2i).meters for p2i in p2]

如果你真的想使用vectorize,你可以使用excluded参数来不向量化p1参数,或者更好的设置包装 vincenty 并且只向量化第二个参数的 lambda:

def vect_dist_funct(p1, p2):
    """Apply `vincenty` to `p1` and each element of `p2`.

    Iterate over `p2`, returning `vincenty` with the first argument
    as `p1` and the second as the current element of `p2`.  Returns
    a list where each value is the result of the `vincenty` function
    call for the corresponding element of `p2`.
    """
    vinc_p = lambda x: vincenty(p1, x)
    return np.vectorize(vinc_p)(p2)

关于python - 将重复参数传递给 Numpy 向量化函数的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38082936/

相关文章:

python - 将 f 字符串语法转换为在旧版本的 python 中打印

python - 光流: get fast motion with Farneback not possible?

python - 如何将数组从ABAB更改为AABB

haskell - Supero(Haskell super 编译器)的用法?

c++ - 与裸 __m128 相比,SSE vector 包装器类型的性能

python - 如何测试 Django 自定义过滤器?

python - 仅在 Gtk.TreeView 中将某些行设为粗体

python - Pandas Series.value_counts() 的奇怪行为

python - 如何将 astropy 表的标题和单位保存到 ascii 文件中

c++ - 尝试优化和理解打印数字除数的递归函数的运行时