【问题标题】:Numpy - How to vectorize on Sub-ArraysNumpy - 如何对子数组进行矢量化
【发布时间】:2020-06-18 06:29:37
【问题描述】:

如何在子数组上应用矢量化函数?假设我有以下内容:

array = np.array([
    [0, 1, 2],
    [2],
    [],
])

我想获取每个子数组中的第一个元素,否则None

[0, 2, None]

虽然简单,但有没有办法利用 Numpy 的纯矢量化来做到这一点?似乎没有原生操作,np.vectorize() 函数被描述为不是真正的文档,并且已在线程中的其他各个点进行了说明。

我唯一的选择是np.apply_along_axes()吗?

我什么时候知道我什么时候不能用 numpy 的纯向量化解决我的问题?

【问题讨论】:

  • 没有真正的矢量化。只需循环。
  • numpy 不允许您拥有非矩形数组。您所指的 sub-arrays 实际上是列表,您不能在其中使用 numpy 工具,而不是对其进行简单循环。

标签: python python-3.x numpy vectorization numpy-ndarray


【解决方案1】:

您已经创建了一个对象 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 的大多数快速编译代码 - “矢量化”的东西 - 仅适用于数字 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-07
    • 1970-01-01
    • 2021-09-19
    相关资源
    最近更新 更多