我想创建一个numpy数组,其中每个元素必须是一个列表,所以稍后我可以将新元素附加到每个元素。
我已经看过google了,这里已经堆栈溢出了,但似乎无处可寻。
主要问题是numpy假设你的列表必须成为一个数组,但这不是我想要的。
答案 0 :(得分:27)
正如您所发现的那样,np.array
尝试在给定类似
A = np.array([[1,2],[3,4]],dtype=object)
你已经应用了一些技巧来解决这个默认行为。
一个是使子列表的长度可变。它不能从这些数组生成二维数组,所以它转向对象数组:
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)
然后,您可以将值附加到每个列表中:
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)
np.empty
还会创建一个对象数组:
In [47]: A=np.empty((3,),dtype=object)
In [48]: A
Out[48]: array([None, None, None], dtype=object)
但是你必须要小心如何将元素更改为列表。 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)
事实证明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]]
初始化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)
从问题和评论中有点不清楚是否要附加到列表或将列表追加到数组中。我刚刚演示了附加到列表中。
有一个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)
您需要构造另一个对象数组以连接到原始对象,例如
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)
在所有这些中,列表数组比列表列表更难构建,并且不易操作或更快。你必须使它成为一个二维数组列表才能获得一些好处。
In [78]: A[:,None]
Out[78]:
array([[[None, 0, 34]],
[[None, 1, 34]],
[[None, 2, 34]]], dtype=object)
您可以重塑,转置等对象数组,其中创建和操作列表列表变得更加复杂。
In [79]: A[:,None].tolist()
Out[79]: [[[None, 0, 34]], [[None, 1, 34]], [[None, 2, 34]]]
答案 1 :(得分:7)
如果你真的需要一个一维的列表数组,你必须将你的列表包装在你自己的类中,因为numpy会一直尝试将你的列表转换为一个数组内的数组(这样更有效但显然需要不变的大小-elements),例如通过
class mylist:
def __init__(self, l):
self.l=l
def __repr__(self):
return repr(self.l)
def append(self, x):
self.l.append(x)
然后你可以在不改变他人维度的情况下改变任何元素
>>> 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)
根据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)
答案 2 :(得分:1)
一种简单的方法是:
A = [[1,2],[3,4]]
B = np.array(A+[[]])[:-1]
答案 3 :(得分:0)
无论如何,列表并不是很麻木,所以也许列表元组对您已经足够了。您可以使用迭代器表达式轻松而高效地获得它:
fiveLists = tuple([] for _ in range(5))
如果您只需要使用一次tuple
(为您提供原始迭代器),则可以省去它。
如果您确实想要的话,可以使用它来创建一个numpy数组:
arrayOfLists = np.fromiter(([] for _ in range(5)), object)
编辑:截至2020年7月,您将获得 “ ValueError:无法从迭代器创建对象数组”
答案 4 :(得分:0)
刚刚找到这个,我之前从未回答过任何问题,但这是一个非常简单的解决方案:
如果要使用长度为n的向量,请使用:
A = np.array([[]]*n + [[1]])[:-1]
这将返回:
array([list([]), list([]), ... , list([])], dtype=object)
如果您想要一个n×m数组,请使用:
A = np.array([[]]*n*m + [[1]])[:-1]
B = A.reshape((n,m))
对于更高级别的数组,可以通过创建长向量并对其进行重塑来使用类似的方法。这可能不是最有效的方法,但对我有用。
答案 5 :(得分:0)
如果您需要从一系列列表或元组中创建数组的数组
x=[[1,2],[3,4],[5,6]]
print(type(x))
print(type(x[0]))
#<class 'list'>
#<class 'list'>
import numpy as np
ar=np.array([np.array(i) for i in x],dtype=object)
print(type(ar))
print(type(ar[0]))
#<class 'numpy.ndarray'>
#<class 'numpy.ndarray'>
答案 6 :(得分:0)
我意识到如果您不需要 Pandas,这是一种解决方法,但它实现了既定目标:
import pandas as pd
A = pd.Series([[1, 2], [3, 4]]).to_numpy()
assert isinstance(A[0], list)
答案 7 :(得分:-1)
data = np.empty(20, dtype=np.object)
for i in range(data.shape[0]):
data[i] = []
data[i].append(i)
print(data)
结果将是:
[列表([0])列表([1])列表([2])列表([3])列表([4])列表([5])列表([6])列表([7 ])列表([8])列表([9])列表([10])列表([11])列表([12])列表([13])列表([14])列表([15]) list([16])list([17])list([18])list([19])]