如何在 numpy 中创建一个“接受”附加的空列表网格?

Posted

技术标签:

【中文标题】如何在 numpy 中创建一个“接受”附加的空列表网格?【英文标题】:How do I make a grid of empty lists in numpy that 'accepts' appending? 【发布时间】:2017-09-14 23:18:09 【问题描述】:

我正在尝试使用 numpy.append 但出现问题,它不再对我有意义。谁能解释我为什么会出错?

>>> np.array([[], [], []]).shape
(3, 0)

>>> a=[[], [], []]
>>> a[1].append(3)
>>> a
[[], [3], []]

>>> b=np.array(a)
>>> b[0].append(3)
array([[3], [3], []], dtype=object)

这对我来说都是合乎逻辑的,但是当我尝试以下操作时它停止工作。

>>> c=np.array((3,0),dtype=object)
>>> c[0].append(3)
AttributeError: 'int' object has no attribute 'append'

????
>>> np.empty((3,1))[0].append(3)
AttributeError: 'numpy.ndarray' object has no attribute 'append'

>>> np.empty((3,0))[1].append(3)
AttributeError: 'numpy.ndarray' object has no attribute 'append'

>>>np.empty((6,1),dtype=object)[0].append(3)
AttributeError: 'numpy.ndarray' object has no attribute 'append'

已解决:How to create a numpy array of lists?

【问题讨论】:

停止向为您提供答案的人提出问题。 如果您有新问题,请提出新问题,而不是编辑同一篇文章。 【参考方案1】:

我知道这是一个相当不寻常的用例,但实际上在每个单元格中都有一个 ndarray 保存列表非常方便。恕我直言 numpy 应该允许将 lambda 函数传递给fill mehtod。但是为了达到你想要的,这就是我所做的:

m = np.empty((12, 12), dtype=object)
for i in np.ndindex(m.shape): m[i] = []

【讨论】:

【参考方案2】:

首先,当有人正确回答您的问题时,请停止更新。接受/赞成一个答案,并在你准备好时提出一个新问题。 SO 是一个问答网站,旨在帮助未来的访问者查看您的问题,而不仅仅是您。至少可以说,为了自己的利益而完全改变上下文来使所有好的答案失效,这违背了本网站的目的。

其次,np.array([[], [3], []])dtype=object 结尾,因为它是一个参差不齐的数组。 [[], [], []][[3], [3], [3]] 在所有维度的所有元素中具有统一的长度,将生成数值数组。

np.zeros((6,),dtype=object) 产生一个空的对象引用数组(包含 NULL)。当您使用[] 填充它时,您将在每个元素中使用对 same python list 的引用来填充它。 numpy 不知道您传递给ndarray.fill 的对象是什么,因此它不会像您期望的那样为每个元素调用list 类型的构造函数。它只是复制您六次传递的引用。在那之后,应该清楚为什么更改该列表的内容会使所有数组元素看起来都已更改。

【讨论】:

是的 fill 应该接受一个 lamda 函数,并最终接受一个参数来停止广播 @KIC。如果您传入一个函数(lambda 只是一个简化的可调用函数),它将复制对该函数的引用。您需要与 fill 完全不同的方法 是的,我的意思是不是。但它应该是一种新功能。 @KIC。我不确定我是否同意这一点。如果你想这样做,你可以使用np.empty 并申请。【参考方案3】:

不要只看形状;检查 dtype,如果是对象,则检查元素的性质

In [282]: np.array([[], [], []])
Out[282]: array([], shape=(3, 0), dtype=float64)

浮点数的二维数组。 np.array 尝试创建一个多维数字数组;只有当它做不到时,它才会创建一个对象数组。

In [283]: b=np.array([[],[3],[]])
In [284]: b
Out[284]: array([[], [3], []], dtype=object)

这里 3 个子列表的大小不同,所以不能做成二维数组;结果是一个对象数组,其中的对象是列表,并且有 append 方法。

In [286]: c=np.array((3,0), object)
In [287]: c
Out[287]: array([3, 0], dtype=object)

这是一个 (2,) 对象数组; 2个元素是数字。数字没有附加方法。

In [288]: np.empty((3,1))
Out[288]: 
array([[ 0.],
       [ 0.],
       [ 0.]])

一个 (3,1) 浮点数组。没有数字或数组的附加方法。

In [289]: np.empty((3,0))
Out[289]: array([], shape=(3, 0), dtype=float64)

另一个二维浮点数组

In [290]: np.empty((6,1),object)
Out[290]: 
array([[None],
       [None],
       [None],
       [None],
       [None],
       [None]], dtype=object)

dtype 对象的二维数组。在这种情况下,它们被初始化为None。再次没有附加方法。

更多关于制作列表数组

dimensions of array of arrays in numpy

How to keep numpy from broadcasting when creating an object array of different shaped arrays


In [305]: d=np.empty((3,),object)
In [306]: d
Out[306]: array([None, None, None], dtype=object)
In [307]: d.fill([])
In [308]: d
Out[308]: array([[], [], []], dtype=object)   # array of lists
In [309]: d[0].append([1,2,3])
In [310]: d
Out[310]: array([[[1, 2, 3]], [[1, 2, 3]], [[1, 2, 3]]], dtype=object)

但是哎呀-这些列表都是同一个对象(指针):(我必须在每个元素中放置一个不同的列表。现在我可以单独附加到它们。

In [311]: d[...]=[[],[1,2,3],[2]]
In [312]: d
Out[312]: array([[], [1, 2, 3], [2]], dtype=object)
In [313]: d[0].append([2,3])
In [314]: d
Out[314]: array([[[2, 3]], [1, 2, 3], [2]], dtype=object)

我认为您必须硬着头皮使用列表来初始化列表的对象数组。没有捷径:

In [319]: d=np.empty((3,),object)
In [320]: d[...]=[[] for _ in range(3)]
In [321]: d
Out[321]: array([[], [], []], dtype=object)
In [323]: d
Out[323]: array([[], [3], []], dtype=object)

【讨论】:

感谢您的回复。您知道为什么我的最后一次编辑会附加到所有列表吗? 出于同样的原因 alist=[[]]*3; alist[0].append[1) 做同样的事情。元素都是相同的列表对象。对象数组,如列表,包含指向内存中其他对象的指针。

以上是关于如何在 numpy 中创建一个“接受”附加的空列表网格?的主要内容,如果未能解决你的问题,请参考以下文章

将列表附加到R中的数据框

如何在 Oz 中创建列表?

如何在 GBQ 中创建具有特定模式的空表?

如何在 SQL Server 中创建一个接受一列数据的函数?

在 VBA 中创建范围

从字典列表中创建NumPy记录数组的最简单方法?