python - 防止 numpy 创建多维数组

标签 python arrays numpy

NumPy 在创建数组时非常有用。如果 numpy.array 的第一个参数有一个 __getitem____len__ 方法,则使用这些方法是因为它可能是一个有效序列。

不幸的是,我想创建一个包含 dtype=object 的数组,而 NumPy 没有“帮助”。

将类分解为一个最小的例子:

import numpy as np

class Test(object):
    def __init__(self, iterable):
        self.data = iterable

    def __getitem__(self, idx):
        return self.data[idx]

    def __len__(self):
        return len(self.data)

    def __repr__(self):
        return '{}({})'.format(self.__class__.__name__, self.data)

如果“iterables”有不同的长度,一切都很好,我得到了我想要的结果:

>>> np.array([Test([1,2,3]), Test([3,2])], dtype=object)
array([Test([1, 2, 3]), Test([3, 2])], dtype=object)

但是如果它们恰好具有相同的长度,NumPy 会创建一个多维数组:

>>> np.array([Test([1,2,3]), Test([3,2,1])], dtype=object)
array([[1, 2, 3],
       [3, 2, 1]], dtype=object)

不幸的是,只有一个 ndmin 参数,所以我想知道是否有办法强制执行 ndmax 或以某种方式阻止 NumPy 将自定义类解释为另一个维度(不删除 __len____getitem__)?

最佳答案

此行为之前已经讨论过多次(例如 Override a dict with numpy support )。 np.array 尝试创建尽可能高的维度数组。模型案例是嵌套列表。如果它可以迭代并且子列表的长度相等,它将“向下钻取”。

在遇到不同长度的列表之前,它下降了 2 级:

In [250]: np.array([[[1,2],[3]],[1,2]],dtype=object)
Out[250]: 
array([[[1, 2], [3]],
       [1, 2]], dtype=object)
In [251]: _.shape
Out[251]: (2, 2)

没有 shape 或 ndmax 参数,它无法知道我想要它是 (2,) 还是 (2,2)。两者都适用于 dtype。

它是经过编译的代码,因此很难准确地看出它使用了哪些测试。它尝试迭代列表和元组,但不迭代集合或字典。

创建具有给定维度的对象数组的最可靠方法是从一个空数组开始,然后填充它

In [266]: A=np.empty((2,3),object)
In [267]: A.fill([[1,'one']])
In [276]: A[:]={1,2}
In [277]: A[:]=[1,2]   # broadcast error

另一种方法是从至少一个不同的元素开始(例如 None),然后替换它。

有一个更原始的创造者,ndarray正在成形:

In [280]: np.ndarray((2,3),dtype=object)
Out[280]: 
array([[None, None, None],
       [None, None, None]], dtype=object)

但这与 np.empty 基本相同(除非我给它一个缓冲区)。

这些都是软糖,但它们并不昂贵(时间方面)。

================(编辑)

https://github.com/numpy/numpy/issues/5933 , Enh: Object array creation function. 是一个增强请求。还有 https://github.com/numpy/numpy/issues/5303 意外不规则数组的错误消息令人困惑

开发人员的情绪似乎倾向于使用一个单独的函数来创建 dtype=object 数组,一个可以更好地控制初始维度和迭代深度的函数。他们甚至可能会加强错误检查以防止 np.array 创建“不规则”数组。

这样的函数可以检测到指定深度的常规嵌套迭代的形状,并构建一个要填充的对象类型数组。

def objarray(alist, depth=1):
    shape=[]; l=alist
    for _ in range(depth):
        shape.append(len(l))
        l = l[0]
    arr = np.empty(shape, dtype=object)
    arr[:]=alist
    return arr

具有不同的深度:

In [528]: alist=[[Test([1,2,3])], [Test([3,2,1])]]
In [529]: objarray(alist,1)
Out[529]: array([[Test([1, 2, 3])], [Test([3, 2, 1])]], dtype=object)
In [530]: objarray(alist,2)
Out[530]: 
array([[Test([1, 2, 3])],
       [Test([3, 2, 1])]], dtype=object)
In [531]: objarray(alist,3)  
Out[531]: 
array([[[1, 2, 3]],

       [[3, 2, 1]]], dtype=object)
In [532]: objarray(alist,4)
...
TypeError: object of type 'int' has no len()

关于python - 防止 numpy 创建多维数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38774922/

相关文章:

python - 尝试读取 DBM 文件

javascript - 字符串中整数的总和 - JS

python - 在python中打开文本文件作为数组或列表列表

python - 读取文本文件并计算概率和香农熵

java - 在 GUI 中显示对象数组

python - 将 1-D numpy 数组转换为 3D RGB 数组

python - 类型错误 : 'numpy.float64' object does not support item assignment

python - 将队列附加到 tensorflow 中的 numpy 数组以获取数据而不是文件?

python - 如何实现 cnn+lstm 模型来预测视频

ruby - 如何填充数组的数组(二维数组)