numpy的反义词,reduce

sxpgvts3  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(96)

所以在numpy中我们有一个reduce函数,我们可以通过将函数应用于该维度上的元素来减少数组的一维。这个函数是否也有一个逆函数,可以将一个元素扩展到一个全新的维度?
假设我有两个数组:

class A:
    def __init__(self, a, b, c):
        self.value = a, b, c

a = np.array([A(1,2,3), A(4,5,6)])
b = np.array([1<<8 | 2<<4 | 3, 4<<8 | 5<<4 | 6])

我想把这两个数组中的任何一个

np.array([[1,2,3],[4,5,6]])

我目前正在做的是:

def expand(arr):
    a = np.empty((*arr.shape, 3))
    for x, y in np.ndindex(arr.shape):
        if isinstance(arr[x,y], A):
            a[x,y] = arr[x,y].value
        else:
            a[x,y] = arr[x,y] >> 8, arr[x,y] >> 4 & 0xF, arr[x,y] & 0xF
    return a

这工作,但我想避免(慢?)迭代,因为它违背了numpy的精神。
我也尝试过使用np.vectorize的解决方案,但它并不像我希望的那样工作:

def expanded(element):
    if isinstance(element, A):
        return element.value
    return element >> 8, element >> 4 & 0xF, element & 0xF
f = np.vectorize(expanded)
f(a)  # Prints a tuple of arrays instead of the desired single array

是否有更好的方法将单个值扩展到新的维度,通过某种数学运算或通过对象属性访问?

fae0ux8s

fae0ux8s1#

您的A示例数组。

In [56]: a
Out[56]: 
array([<__main__.A object at 0x000001BE0C814220>,
       <__main__.A object at 0x000001BE138B8610>], dtype=object)

定义一个__repr__以获得更漂亮的显示。
在示例上迭代,返回value

In [59]: [np.array(i.value) for i in a]
Out[59]: [array([1, 2, 3]), array([4, 5, 6])]

它可以转换为一个数组,其中:

In [60]: np.vstack(_)
Out[60]: 
array([[1, 2, 3],
       [4, 5, 6]])

In [61]: np.array(__)
Out[61]: 
array([[1, 2, 3],
       [4, 5, 6]])

vectorize为示例返回的每个值创建一个数组,这里有3个数组:

In [62]: np.vectorize(lambda i: i.value)(a)
Out[62]: (array([1, 4]), array([2, 5]), array([3, 6]))

它可以被转换为前一个数组的转置:

In [63]: np.array(_)
Out[63]: 
array([[1, 4],
       [2, 5],
       [3, 6]])

返回一个数组(而不是元组),并指定otypes,给出另一个对象dtype array:

In [64]: np.vectorize(lambda i: np.array(i.value), otypes=[object])(a)
Out[64]: array([array([1, 2, 3]), array([4, 5, 6])], dtype=object)
In [65]: np.vstack(_)
Out[65]: 
array([[1, 2, 3],
       [4, 5, 6]])

signature可以直接生成数字数组。我不认为这会更快。

In [66]: np.vectorize(lambda i: np.array(i.value), signature='()->(n)')(a)
Out[66]: 
array([[1, 2, 3],
       [4, 5, 6]])

vectorize的一个更基本的版本直接返回一个对象dtype数组:

In [68]: np.frompyfunc(lambda i: np.array(i.value), 1,1)(a)
Out[68]: array([array([1, 2, 3]), array([4, 5, 6])], dtype=object)

这个小例子的比较时间不会告诉我们太多。你需要探索一个更现实的大小a
快速numpy代码适用于数字数据类型。对于对象,dtype的速度都近似等于列表解析。

相关问题