Numpy - 如何对子数组进行矢量化
Numpy - How to vectorize on Sub-Arrays
如何在子数组上应用向量化函数?假设我有以下内容:
array = np.array([
[0, 1, 2],
[2],
[],
])
而我想获取每个子数组中的第一个元素,否则None
。
[0, 2, None]
虽然简单,但有没有办法利用 Numpy 的纯矢量化来做到这一点?似乎没有本机操作,np.vectorize()
函数被描述为不是真正的文档,并且已在线程中的其他各个点进行了说明。
我唯一的选择是 np.apply_along_axes()
吗?
我什么时候知道无法使用 numpy 的纯矢量化解决我的问题?
您已经创建了一个对象 dtype 数组 - 包含列表(不是子数组):
In [2]: array = np.array([
...: [0, 1, 2],
...: [2],
...: [],
...: ])
/usr/local/bin/ipython3:4: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (1.19dev gives warning)
In [3]: array
Out[3]: array([list([0, 1, 2]), list([2]), list([])], dtype=object)
我们可以使用列表理解:
In [4]: [a[0] for a in array]
....
IndexError: list index out of range
并更正空列表:
In [5]: [a[0] if a else None for a in array]
Out[5]: [0, 2, None]
大多数 numpy
的快速编译代码 - "vectorized" 东西 - 仅适用于数字 dtype 数组。对于 object dtype,它必须做一些类似于列表理解的事情。即使数学有效,那也是因为它能够将操作委托给元素。
例如,将列表复制应用于数组的所有元素:
In [7]: array*3
Out[7]:
array([list([0, 1, 2, 0, 1, 2, 0, 1, 2]), list([2, 2, 2]), list([])],
dtype=object)
和 sum
只是列表连接:
In [8]: array.sum()
Out[8]: [0, 1, 2, 2]
apply_along_axis
并不比 np.vectorize
快。我无法想象在这种情况下会如何使用它。 array
是 1d。
有时 frompyfunc
在处理对象 dtype 数组时很方便(但这不是速度解决方案):
In [11]: timeit np.frompyfunc(lambda a: a[0] if a else None, 1,1)(array)
3.8 µs ± 9.85 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [12]: timeit [a[0] if a else None for a in array]
1.02 µs ± 5.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [14]: timeit np.vectorize(lambda a: a[0] if a else None, otypes=['O'])(array)
18 µs ± 46.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
如何在子数组上应用向量化函数?假设我有以下内容:
array = np.array([
[0, 1, 2],
[2],
[],
])
而我想获取每个子数组中的第一个元素,否则None
。
[0, 2, None]
虽然简单,但有没有办法利用 Numpy 的纯矢量化来做到这一点?似乎没有本机操作,np.vectorize()
函数被描述为不是真正的文档,并且已在线程中的其他各个点进行了说明。
我唯一的选择是 np.apply_along_axes()
吗?
我什么时候知道无法使用 numpy 的纯矢量化解决我的问题?
您已经创建了一个对象 dtype 数组 - 包含列表(不是子数组):
In [2]: array = np.array([
...: [0, 1, 2],
...: [2],
...: [],
...: ])
/usr/local/bin/ipython3:4: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (1.19dev gives warning)
In [3]: array
Out[3]: array([list([0, 1, 2]), list([2]), list([])], dtype=object)
我们可以使用列表理解:
In [4]: [a[0] for a in array]
....
IndexError: list index out of range
并更正空列表:
In [5]: [a[0] if a else None for a in array]
Out[5]: [0, 2, None]
大多数 numpy
的快速编译代码 - "vectorized" 东西 - 仅适用于数字 dtype 数组。对于 object dtype,它必须做一些类似于列表理解的事情。即使数学有效,那也是因为它能够将操作委托给元素。
例如,将列表复制应用于数组的所有元素:
In [7]: array*3
Out[7]:
array([list([0, 1, 2, 0, 1, 2, 0, 1, 2]), list([2, 2, 2]), list([])],
dtype=object)
和 sum
只是列表连接:
In [8]: array.sum()
Out[8]: [0, 1, 2, 2]
apply_along_axis
并不比 np.vectorize
快。我无法想象在这种情况下会如何使用它。 array
是 1d。
有时 frompyfunc
在处理对象 dtype 数组时很方便(但这不是速度解决方案):
In [11]: timeit np.frompyfunc(lambda a: a[0] if a else None, 1,1)(array)
3.8 µs ± 9.85 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [12]: timeit [a[0] if a else None for a in array]
1.02 µs ± 5.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [14]: timeit np.vectorize(lambda a: a[0] if a else None, otypes=['O'])(array)
18 µs ± 46.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)