如何创建一个numpy列表?

Ric*_*ira 29 python arrays numpy list

我想创建一个numpy数组,其中每个元素必须是一个列表,所以稍后我可以向每个元素添加新元素.

我已经看过谷歌,这里已经堆栈溢出,但似乎无处可寻.

主要问题是numpy假设你的列表必须成为一个数组,但这不是我想要的.

hpa*_*ulj 33

正如您所发现的那样,np.array尝试在给定类似内容时创建二维数组

 A = np.array([[1,2],[3,4]],dtype=object)
Run Code Online (Sandbox Code Playgroud)

您已应用一些技巧来绕过此默认行为.

一种是使子列表的长度可变.它不能从这些数组生成二维数组,所以它转向对象数组:

In [43]: A=np.array([[1,2],[],[1,2,3,4]])
In [44]: A
Out[44]: array([[1, 2], [], [1, 2, 3, 4]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

然后,您可以将值附加到每个列表中:

In [45]: for i in A: i.append(34)
In [46]: A
Out[46]: array([[1, 2, 34], [34], [1, 2, 3, 4, 34]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

np.empty 还会创建一个对象数组:

In [47]: A=np.empty((3,),dtype=object)
In [48]: A
Out[48]: array([None, None, None], dtype=object)
Run Code Online (Sandbox Code Playgroud)

但是,您必须小心如何将元素更改为列表. np.fill很诱人,但有问题:

In [49]: A.fill([])
In [50]: A
Out[50]: array([[], [], []], dtype=object)
In [51]: for i in A: i.append(34)
In [52]: A
Out[52]: array([[34, 34, 34], [34, 34, 34], [34, 34, 34]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

事实证明,fill在所有插槽中放置相同的列表,因此修改一个列表会修改所有其他插槽.您可以通过列表列表获得相同的问题:

In [53]: B=[[]]*3
In [54]: B
Out[54]: [[], [], []]
In [55]: for i in B: i.append(34)
In [56]: B
Out[56]: [[34, 34, 34], [34, 34, 34], [34, 34, 34]]
Run Code Online (Sandbox Code Playgroud)

初始化的正确方法empty A是迭代,例如

In [65]: A=np.empty((3,),dtype=object)
In [66]: for i,v in enumerate(A): A[i]=[v,i]
In [67]: A
Out[67]: array([[None, 0], [None, 1], [None, 2]], dtype=object)
In [68]: for v in A: v.append(34)
In [69]: A
Out[69]: array([[None, 0, 34], [None, 1, 34], [None, 2, 34]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

从问题和评论中有点不清楚是否要附加到列表或将列表附加到数组.我刚刚演示了附加到列表中.

有一个np.append功能,新用户经常滥用.它不能替代列表追加.这是一个前端np.concatenate.它不是就地操作; 它返回一个新数组.

定义要添加的列表也很棘手:

In [72]: np.append(A,[[1,23]])
Out[72]: array([[None, 0, 34], [None, 1, 34], [None, 2, 34], 1, 23],     dtype=object)
Run Code Online (Sandbox Code Playgroud)

您需要构造另一个对象数组以连接到原始对象,例如

In [76]: np.append(A,np.empty((1,),dtype=object))
Out[76]: array([[None, 0, 34], [None, 1, 34], [None, 2, 34], None], dtype=object)
Run Code Online (Sandbox Code Playgroud)

在所有这些中,列表数组比列表列表更难构建,并且不易操作或更快.你必须使它成为一个列表的二维数组才能获得一些好处.

In [78]: A[:,None]
Out[78]: 
array([[[None, 0, 34]],
       [[None, 1, 34]],
       [[None, 2, 34]]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

您可以重塑,转置等对象数组,其中创建和操作列表列表变得更加复杂.

In [79]: A[:,None].tolist()
Out[79]: [[[None, 0, 34]], [[None, 1, 34]], [[None, 2, 34]]]
Run Code Online (Sandbox Code Playgroud)


lej*_*lot 7

如果你真的需要一个一维的列表数组,你必须将你的列表包装在你自己的类中,因为numpy总会尝试将你的列表转换为一个数组内的数组(这样更有效,但显然需要不变的大小元素) ,例如通过

class mylist:

    def __init__(self, l):
        self.l=l

    def __repr__(self): 
        return repr(self.l)

    def append(self, x):
        self.l.append(x)
Run Code Online (Sandbox Code Playgroud)

然后你可以改变任何元素而不改变其他元素的维度

>>> x = mylist([1,2,3])
>>> y = mylist([1,2,3])
>>> import numpy as np
>>> data = np.array([x,y])
>>> data
array([[1,2,3], [1,2,3]], dtype=object)
>>> data[0].append(2)
>>> data
array([[1,2,3,2], [1,2,3]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

更新

正如所建议的ali_m,实际上有一种方法可以强迫numpy简单地为引用创建一维数组,然后用实际列表提供它们

>>> data = np.empty(2, dtype=np.object)
>>> data[:] = [1, 2, 3], [1, 2, 3]
>>> data
array([[1, 2, 3], [1, 2, 3]], dtype=object)
>>> data[0].append(4)
>>> data
array([[1, 2, 3, 4], [1, 2, 3]], dtype=object)
Run Code Online (Sandbox Code Playgroud)

  • 您无需使用`data = np.empty(2,dtype = np.object);定义新类就可以达到相同的结果。数据[:] = [1,2,3],[1,2,3]` (2认同)

小智 6

data = np.empty(20, dtype=np.object)
for i in range(data.shape[0]):
    data[i] = []
    data[i].append(i)
print(data)
Run Code Online (Sandbox Code Playgroud)

结果将是:

[list([0]) list([1]) list([2]) list([3]) list([4]) list([5]) list([6]) list([7]) list([8]) list([9]) list([10]) list([11]) list([12]) list([13]) list([14]) list([15]) list([16]) list([17]) list([18]) list([19])]
Run Code Online (Sandbox Code Playgroud)