gpt4 book ai didi

python - np.vectorize 和 np.apply_along_axis 两次将相同的参数传递给映射函数

转载 作者:太空宇宙 更新时间:2023-11-04 07:14:11 24 4
gpt4 key购买 nike

我想将一个函数 f 映射到一个字符串数组上。我构建了 f 的矢量化版本并将其应用于我的数组。但是数组的第一个元素被传递了两次:

import numpy as np

def f(string):
print('called with', string)

a = np.array(['110', '012'])

fv = np.vectorize(f)
np.apply_along_axis(fv, axis=0, arr=a)


called with 110
called with 110
called with 012

这是为什么呢?我没想到 110 会被传递给 f 两次,我不明白为什么会这样。

我对 np.vectorizenp.apply_along_axis 的误解是什么?

最佳答案

In [145]: def f(string):
...: print('called with', string)
...:
...: a = np.array(['110', '012'])
...:
...: fv = np.vectorize(f)
...:
In [146]: fv(a)
called with 110
called with 110
called with 012
Out[146]: array([None, None], dtype=object)

只有打印的函数返回Nonevectorized 调用它一次以确定返回数据类型 - 在本例中它推导出 object

如果我们指定一个 otypesint,我们会得到一个错误:

In [147]: fv = np.vectorize(f, otypes=[int])
In [148]: fv(a)
called with 110
called with 012
---------------------------------------------------------------------------
...
TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'

otypes 与返回的对象不兼容

In [149]: fv = np.vectorize(f, otypes=[object])
In [150]: fv(a)
called with 110
called with 012
Out[150]: array([None, None], dtype=object)

一个更好的、更有意义的函数:

In [151]: def f(string):
...: print('called with', string)
...: return len(string)
...:
...:
In [152]: fv = np.vectorize(f, otypes=[int])
In [153]: fv(a)
called with 110
called with 012
Out[153]: array([3, 3])

请记住,vectorize 将标量值传递给您的函数。实际上,它评估输入数组的每个元素,返回具有匹配形状的数组:

In [154]: fv(np.array([a,a,a]))
called with 110
called with 012
called with 110
called with 012
called with 110
called with 012
Out[154]:
array([[3, 3],
[3, 3],
[3, 3]])

与普通迭代相比,例如。 np.array([f(i) for i in a]),速度较慢,但​​如果输入数组可以有多个维度,则更方便一些,如果有多个数组,则更好需要互相广播。

对于像 a 这样的简单数组,np.vectorize 是多余的。


vectorize 有另一个参数,cache 可以避免这种双重调用,同时仍然允许自动数据类型检测:

In [156]: fv = np.vectorize(f, cache=True)
In [157]: fv(a)
called with 110
called with 012
Out[157]: array([3, 3])

自动数据类型检测有时会导致错误。例如,如果试算返回不同的数据类型:

In [160]: def foo(var):
...: if var<0:
...: return -var
...: elif var>0:
...: return var
...: else:
...: return 0

In [161]: np.vectorize(foo)([0,1.2, -1.2])
Out[161]: array([0, 1, 1]) # int dtype
In [162]: np.vectorize(foo)([0.1,1.2, -1.2])
Out[162]: array([0.1, 1.2, 1.2]) # float dtype

apply_along_axis 采用接受一维数组的函数。它遍历所有其他维度,将一组一维切片传递给您的函数。对于像您的 a 这样的一维数组,这没有任何用处。即使找到了 a,也无济于事。您的 fv 不需要一维输入。

它也进行了试算以确定返回数组的形状和数据类型。它会自动缓存该结果。

vectorize一样,apply_along_axis是一种便利工具,而不是性能工具。

比较

np.apply_along_axis(fv, axis=0, arr=[a,a,a])
np.apply_along_axis(fv, axis=1, arr=[a,a,a])

了解 apply_along 如何影响计算顺序。

或者对整个(或列)做一些事情:

np.apply_along_axis(lambda x: fv(x).mean(), axis=0, arr=[a,a,a])

关于python - np.vectorize 和 np.apply_along_axis 两次将相同的参数传递给映射函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54295812/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com