我想创建一个 numpy 数组,其中每个元素必须是一个列表,因此稍后我可以向每个元素追加新元素。
我已经在谷歌和这里的堆栈溢出上查看过,但似乎无处可寻。
主要问题是 numpy 假设你的列表必须成为一个数组,但这不是我想要的。
正如您所发现的,
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]]]
===
如https://stackoverflow.com/a/57364472/901925所示,
np.frompyfunc
是创建对象数组的好工具。
np.frompyfunc(list, 0, 1)(np.empty((3,2), dtype=object))
如果你确实需要一个一维列表数组,你必须将列表包装在你自己的类中,因为 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)
然后你可以改变任何元素而不改变其他元素的尺寸
>>> 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)
data = np.empty(20, dtype=np.object)
for i in range(data.shape[0]):
data[i] = []
data[i].append(i)
print(data)
结果将是:
[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])]
一个简单的方法是:
A = [[1,2],[3,4]]
B = np.array(A+[[]])[:-1]
刚刚发现这个,我以前从未回答过问题,但这是一个非常简单的解决方案:
如果你想要一个长度为 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))
对于更高阶的数组,您可以使用类似的方法,创建一个长向量并对其进行整形。 这可能不是最有效的方法,但它对我有用。
列表无论如何都不是很麻木,所以也许列表的元组对你来说就足够了。您可以使用迭代器表达式轻松且高效地获得此结果:
fiveLists = tuple([] for _ in range(5))
如果您只需要一次,您可以省略
tuple
(为您提供原始迭代器)。
如果你真的想的话,你可以用它来创建一个 numpy 数组:
arrayOfLists = np.fromiter(([] for _ in range(5)), object)
编辑:截至 2020 年 7 月,您将获得 “ValueError:无法从迭代器创建对象数组”
如果您需要从一系列列表或元组创建数组的数组
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'>
我意识到,如果你不需要 Pandas,这是一个解决方法,但它实现了既定的目标:
import pandas as pd
A = pd.Series([[1, 2], [3, 4]]).to_numpy()
assert isinstance(A[0], list)
Numpy array() 确实支持
ndmin
参数,它允许您设置输出数组中的 minumim 维数,但不幸的是(尚)不支持 ndmax
参数,这将允许这种情况发生很容易。
同时,这里有一个小函数,它将根据任意嵌套序列创建一个一维数组:
def create_1d_array(seq: Sequence) -> np.ndarray:
arr = np.empty(len(seq), dtype=object)
arr[:] = [s for s in seq]
return arr
>>> create_1d_array([[1, 2], [3, 4]])
array([list([1, 2]), list([3, 4])], dtype=object)
我遇到了同样的问题,列表的元素作为单独的元素而不是列表添加到数组中。 在@hpaulj 的帮助下,我解决了这个问题,就像这样简单:
array_of_lists = np.array(np.empty(1, dtype=object))
array_of_lists[0] = first_list
if second_list:
array_of_lists = np.append(array_of_lists, np.empty(1, dtype=object))
array_of_lists[1] = second_list
if third_list:
array_of_lists = np.append(array_of_lists, np.empty(1, dtype=object))
array_of_lists[2] = third_list
希望这可以帮助别人。
所以这个答案很晚了,并没有完全解决这个问题,但它解决了我遇到的导致这个问题的问题...我想要一个列表数组...
...请注意,这不会给出 numpy 数组
n 个列表的数组的解决方案是
listarray=[]
for i in range(n)
listarray.append([])
这给出了一个空列表的列表,您可以将您想要的任何内容附加到每个成员,例如
for i in range(n):
listarray[i].append(0.1*i)
for i in range(n):
listarray[i].append(0.2*i)
for i in range(n):
listarray[i].append(0.4*i)
对于 n=3 这段代码给出
print(listarray)
[[0.0, 0.0, 0.0], [0.1, 0.2, 0.4], [0.2, 0.4, 0.8]]