如何创建列表的 numpy 数组?

问题描述 投票:0回答:11

我想创建一个 numpy 数组,其中每个元素必须是一个列表,因此稍后我可以向每个元素追加新元素。

我已经在谷歌和这里的堆栈溢出上查看过,但似乎无处可寻。

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

python arrays list numpy
11个回答
69
投票

正如您所发现的,

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))  

10
投票

如果你确实需要一个一维列表数组,你必须将列表包装在你自己的类中,因为 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)

6
投票
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])]

2
投票

一个简单的方法是:

A = [[1,2],[3,4]] 
B = np.array(A+[[]])[:-1]

2
投票

刚刚发现这个,我以前从未回答过问题,但这是一个非常简单的解决方案:

如果你想要一个长度为 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))

对于更高阶的数组,您可以使用类似的方法,创建一个长向量并对其进行整形。 这可能不是最有效的方法,但它对我有用。


0
投票

列表无论如何都不是很麻木,所以也许列表的元组对你来说就足够了。您可以使用迭代器表达式轻松且高效地获得此结果:

fiveLists = tuple([] for _ in range(5))

如果您只需要一次,您可以省略

tuple
(为您提供原始迭代器)。

如果你真的想的话,你可以用它来创建一个 numpy 数组:

arrayOfLists = np.fromiter(([] for _ in range(5)), object)

编辑:截至 2020 年 7 月,您将获得 “ValueError:无法从迭代器创建对象数组”


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'>

0
投票

我意识到,如果你不需要 Pandas,这是一个解决方法,但它实现了既定的目标:

import pandas as pd

A = pd.Series([[1, 2], [3, 4]]).to_numpy()
assert isinstance(A[0], list)

0
投票

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)

0
投票

我遇到了同样的问题,列表的元素作为单独的元素而不是列表添加到数组中。 在@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

希望这可以帮助别人。


0
投票

所以这个答案很晚了,并没有完全解决这个问题,但它解决了我遇到的导致这个问题的问题...我想要一个列表数组...

...请注意,这不会给出 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]]
© www.soinside.com 2019 - 2024. All rights reserved.