Using Numpy Vectorize on Functions that Return Vectors
当
例如:
1 2 3 4 5 6 | import numpy as np def f(x): return x * np.array([1,1,1,1,1], dtype=np.float32) g = np.vectorize(f, otypes=[np.ndarray]) a = np.arange(4) print(g(a)) |
这样产生:
1 2 3 4 | array([[ 0. 0. 0. 0. 0.], [ 1. 1. 1. 1. 1.], [ 2. 2. 2. 2. 2.], [ 3. 3. 3. 3. 3.]], dtype=object) |
好的,这样就给出了正确的值,但dtype错误。 更糟糕的是:
1 | g(a).shape |
产量:
1 | (4,) |
所以这个数组几乎没有用。 我知道我可以将其转换为:
1 | np.array(map(list, a), dtype=np.float32) |
给我我想要的东西:
1 2 3 4 | array([[ 0., 0., 0., 0., 0.], [ 1., 1., 1., 1., 1.], [ 2., 2., 2., 2., 2.], [ 3., 3., 3., 3., 3.]], dtype=float32) |
但这既没有效率,也没有pythonic。 你们中有人可以找到一种更清洁的方法吗?
提前致谢!
您的函数
因此,解决方案只是滚动您自己的函数
1.12.0中的新参数
1 2 3 4 | def f(x): return x * np.array([1,1,1,1,1], dtype=np.float32) g = np.vectorize(f, signature='()->(n)') |
然后
在此指定
1 2 3 4 5 6 7 8 9 10 11 12 | import numpy as np def f(x): return x * np.array([1,1,1,1,1], dtype=np.float32) g = np.vectorize(f, otypes=[np.ndarray]) a = np.arange(4) b = g(a) b = np.array(b.tolist()) print(b)#b.shape = (4,5) c = np.ones((2,3,4)) d = g(c) d = np.array(d.tolist()) print(d)#d.shape = (2,3,4,5) |
这应该可以解决该问题,并且无论输入大小如何,它都可以工作。"地图"仅适用于一个三维输入。使用" .tolist()"并创建一个新的ndarray可以更完全,更好地解决该问题(我相信)。希望这可以帮助。
我已经编写了一个函数,它似乎适合您的需求。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | def amap(func, *args): '''array version of build-in map amap(function, sequence[, sequence, ...]) -> array Examples -------- >>> amap(lambda x: x**2, 1) array(1) >>> amap(lambda x: x**2, [1, 2]) array([1, 4]) >>> amap(lambda x,y: y**2 + x**2, 1, [1, 2]) array([2, 5]) >>> amap(lambda x: (x, x), 1) array([1, 1]) >>> amap(lambda x,y: [x**2, y**2], [1,2], [3,4]) array([[1, 9], [4, 16]]) ''' args = np.broadcast(None, *args) res = np.array([func(*arg[1:]) for arg in args]) shape = args.shape + res.shape[1:] return res.reshape(shape) |
让我们尝试
1 2 3 | def f(x): return x * np.array([1,1,1,1,1], dtype=np.float32) amap(f, np.arange(4)) |
产出
1 2 3 4 | array([[ 0., 0., 0., 0., 0.], [ 1., 1., 1., 1., 1.], [ 2., 2., 2., 2., 2.], [ 3., 3., 3., 3., 3.]], dtype=float32) |
为了方便起见,您也可以用lambda或部分包装
1 2 | g = lambda x:amap(f, x) g(np.arange(4)) |
注意
The
vectorize function is provided primarily for convenience, not for
performance. The implementation is essentially a for loop.
因此,我们希望此处的
如果性能确实很重要,则应考虑其他因素,例如使用
解决此问题的最佳方法是使用2-D NumPy数组(在本例中为列数组)作为原始函数的输入,然后该函数将生成2-D输出,并带有我认为您期望的结果。
这是代码中的样子:
1 2 3 4 5 6 7 8 | import numpy as np def f(x): return x*np.array([1, 1, 1, 1, 1], dtype=np.float32) a = np.arange(4).reshape((4, 1)) b = f(a) # b is a 2-D array with shape (4, 5) print(b) |
这是一种更简单,更不易出错的方式来完成操作。此方法不是尝试使用numpy.vectorize转换函数,而是依靠NumPy的自然能力来广播数组。诀窍是要确保至少一维数组之间的长度相等。