Python 如何制作具有不同行大小的多维numpy数组?

Python 如何制作具有不同行大小的多维numpy数组?,python,arrays,numpy,Python,Arrays,Numpy,我想创建一个二维numpy数组,数组的每一行上有不同数量的元素 尝试 cells = numpy.array([[0,1,2,3], [2,3,4]]) 给出一个错误 ValueError: setting an array element with a sequence. 虽然Numpy知道任意对象的数组,但它针对具有固定维度的同构数字数组进行了优化。如果确实需要数组的数组,最好使用嵌套列表。但是,根据数据的预期用途,不同的数据结构可能更好,例如,如果您有一些无效的数据点,则使用屏蔽数组

我想创建一个二维numpy数组,数组的每一行上有不同数量的元素

尝试

cells = numpy.array([[0,1,2,3], [2,3,4]])
给出一个错误

ValueError: setting an array element with a sequence.

虽然Numpy知道任意对象的数组,但它针对具有固定维度的同构数字数组进行了优化。如果确实需要数组的数组,最好使用嵌套列表。但是,根据数据的预期用途,不同的数据结构可能更好,例如,如果您有一些无效的数据点,则使用屏蔽数组

如果您确实想要灵活的Numpy阵列,请使用以下方法:

numpy.array([[0,1,2,3], [2,3,4]], dtype=object)

但是,这将创建一个存储列表引用的一维数组,这意味着您将失去Numpy的大部分好处(向量处理、局部性、切片等)。

这在Numpy中不受很好的支持(根据定义,“二维数组”几乎在任何地方都具有相同长度的所有行)。Python Numpy数组列表对您来说可能是一个很好的解决方案,因为这样您可以在可以使用它们的地方获得Numpy的优势:

cells = [numpy.array(a) for a in [[0,1,2,3], [2,3,4]]]

我们现在差不多7年前就提出了这个问题,你的代码

cells = numpy.array([[0,1,2,3], [2,3,4]])
在Numpy1.12.0和Python3.5中执行,不会产生任何错误和错误
单元格
包含:

array([[0, 1, 2, 3], [2, 3, 4]], dtype=object)
您可以将
单元格
元素作为
单元格[0][2]#(=2)
访问

如果要在新元素(即数组)可用时动态生成numpy数组列表,另一种方法是使用
append

d = []                 # initialize an empty list
a = np.arange(3)       # array([0, 1, 2])
d.append(a)            # [array([0, 1, 2])]
b = np.arange(3,-1,-1) #array([3, 2, 1, 0])
d.append(b)            #[array([0, 1, 2]), array([3, 2, 1, 0])]

另一种选择是将数组存储为一个连续数组,并存储其大小或偏移量。这需要对如何在数组上操作进行更多的概念性思考,但令人惊讶的是,可以进行大量操作,就像有一个大小不同的二维数组一样。如果不能,则可以使用
np.split
创建calocedrus建议的列表。最简单的操作是UFUNC,因为它们几乎不需要修改。以下是一些例子:

cells_flat = numpy.array([0, 1, 2, 3, 2, 3, 4])
# One of these is required, it's pretty easy to convert between them,
# but having both makes the examples easy
cell_lengths = numpy.array([4, 3])
cell_starts = numpy.insert(cell_lengths[:-1].cumsum(), 0, 0)
cell_lengths2 = numpy.diff(numpy.append(cell_starts, cells_flat.size))
assert np.all(cell_lengths == cell_lengths2)

# Copy prevents shared memory
cells = numpy.split(cells_flat.copy(), cell_starts[1:])
# [array([0, 1, 2, 3]), array([2, 3, 4])]

numpy.array([x.sum() for x in cells])
# array([6, 9])
numpy.add.reduceat(cells_flat, cell_starts)
# array([6, 9])

[a + v for a, v in zip(cells, [1, 3])]
# [array([1, 2, 3, 4]), array([5, 6, 7])]
cells_flat + numpy.repeat([1, 3], cell_lengths)
# array([1, 2, 3, 4, 5, 6, 7])

[a.astype(float) / a.sum() for a in cells]
# [array([ 0.        ,  0.16666667,  0.33333333,  0.5       ]),
#  array([ 0.22222222,  0.33333333,  0.44444444])]
cells_flat.astype(float) / np.add.reduceat(cells_flat, cell_starts).repeat(cell_lengths)
# array([ 0.        ,  0.16666667,  0.33333333,  0.5       ,  0.22222222,
#         0.33333333,  0.44444444])

def complex_modify(array):
    """Some complicated function that modifies array

    pretend this is more complex than it is"""
    array *= 3

for arr in cells:
    complex_modify(arr)
cells
# [array([0, 3, 6, 9]), array([ 6,  9, 12])]
for arr in numpy.split(cells_flat, cell_starts[1:]):
    complex_modify(arr)
cells_flat
# array([ 0,  3,  6,  9,  6,  9, 12])

在numpy 1.14.3中,使用append:

d = []                 # initialize an empty list
a = np.arange(3)       # array([0, 1, 2])
d.append(a)            # [array([0, 1, 2])]
b = np.arange(3,-1,-1) #array([3, 2, 1, 0])
d.append(b)            #[array([0, 1, 2]), array([3, 2, 1, 0])]
您将得到一个数组列表(可以是不同长度的数组),您可以执行类似于
d[0].mean()的操作。另一方面,

cells = numpy.array([[0,1,2,3], [2,3,4]])
结果是一个列表数组

您可能需要执行以下操作:

a1 = np.array([1,2,3])
a2 = np.array([3,4])
a3 = np.array([a1,a2])
a3 # array([array([1, 2, 3]), array([3, 4])], dtype=object)
type(a3) # numpy.ndarray
type(a2) # numpy.ndarray

有点离题,但没有人们想象的那么多,因为现在的默认模式是渴望模式: 如果使用Tensorflow,可以执行以下操作:

a = tf.ragged.constant([[0, 1, 2, 3]])
b = tf.ragged.constant([[2, 3, 4]])
c = tf.concat([a, b], axis=0)
然后你仍然可以做所有的数学运算,比如
tf.math.reduce\u mean
,等等
np.array([[0,1,2,3],[2,3,4]],dtype=object)
返回一个列表的“数组”

a=np.array([np.array([0,1,2,3]),np.array([2,3,4]),dtype=object)
返回数组的数组。它已经允许诸如
a+1
之类的操作

在此基础上,可以通过子类化来增强功能

将numpy导入为np
类数组(np.ndarray):
def\uuuu新建(cls,输入数组,dims=None):
obj=np.array(列表(映射(np.array,输入数组))).view(cls)
返回obj
定义获取项目(自我,ij):
如果isinstance(ij,元组)和len(ij)>1:
#处理二维切片
如果isinstance(ij[0],slice)或hasattr(ij[0]),则“\uu iter”:
#[1:4]:]或[1,2,3],[1,2]]
返回数组(自[ij[0]]中的arr的arr[ij[1]]
返回self[ij[0]][ij[1]]#[1,:]np.array
返回super(数组,self)。\uuu getitem\uuuj(ij)
定义数组(self,ufunc,method,*输入,**kwargs):
axis=kwargs.pop('axis',无)
dimk=[len(arg)如果hasattr(arg,'.''.'iter'.'else 1表示输入中的arg]
dim=最大值(dimk)

pad_inputs=[([i]*dim if(d问题是仍然不能使用d.mean(),d.flatte())等等。这是最理想的方法吗?numpy阵列仍然应该是长度均匀的2D阵列吗?如果是,存储可变长度数据的最佳方法是什么。这是一个很好的解决方案。巧妙地使用
reduceat
+1 numpy“了解”意味着什么任意对象数组?请记住:关于内存使用:Python整数列表比numpy整数数组效率低得多。我的意思是,除去列表或数组对象元的少量开销,包含
N
整数的列表内容需要
(28+8)*N
字节,但numpy需要
(8*N)
或者您可以使用
np.int16
np.int32
等将其缩减为
2*N
4*N
字节。@ThammeGowda python将每个整数存储为PyObject,因此其开销比numpy大得多。@JiaHaoXu,这就是我说的!我说python的列表比numpy效率低。哦,对不起,我看错了t作为“高效”xD
a = Arrays([[0,1,2,3], [2,3,4]])
a[0:1,0:-1]
# Arrays([[0, 1, 2]])
np.sin(a)
# Arrays([array([0.        , 0.84147098, 0.90929743, 0.14112001]),
#        array([ 0.90929743,  0.14112001, -0.7568025 ])], dtype=object)
a + 2*a
# Arrays([array([0, 3, 6, 9]), array([ 6,  9, 12])], dtype=object)
# patch for nanfunction that cannot handle the object-ndarrays along with second axis=-1
def nanpatch(func):
    def wrapper(a, axis=None, **kwargs):
        if isinstance(a, Arrays):
            rowresult = [func(x, **kwargs) for x in a]
            if axis == 1:
                return np.array(rowresult)
            else:
                # repeat over remaining axis
                return func(rowresult)
        # otherwise keep the original version
        return func(a, axis=axis, **kwargs)
    return wrapper

np.nanmean = nanpatch(np.nanmean)
np.nansum = nanpatch(np.nansum)
np.nanmin = nanpatch(np.nanmin)
np.nanmax = nanpatch(np.nanmax)
np.nansum(a)
# 15
np.nansum(a, axis=1)
# array([6, 9])