在二维数组中追加/连接数组

Posted

技术标签:

【中文标题】在二维数组中追加/连接数组【英文标题】:Appending/concatenating arrays inside 2D array 【发布时间】:2018-04-18 13:15:24 【问题描述】:

我正在尝试生成一个 3x4 数组,其中每个元素都将成为一个未知大小的数组。在此过程中,我将新数字一一附加到 3x4 矩阵的某些单元格中。我最终希望得到一个如下所示的数组:

[[[1,8,9],[1,2],[],[]],
[[8],[],[4,5],[9,1]],
[[],[7,1,4],[],[2,1,3]]]

现在我一直在尝试使用追加和连接,但我似乎找不到一个好的方法来做到这一点,因为内部数组的大小会发生变化。另外我不知道初始化矩阵的最佳方法是什么。简化后,我的代码如下所示:

mat = np.empty((3,4,1))
for x in range(1000):
    i, j, value = somefunction()
    mat[i,j,:] = np.append(mat[i,j,:], value)

有人知道将这些值附加(或连接或...)到我的矩阵的最佳方法吗?我一直在查找有关附加和连接的类似问题,并尝试了很多不同的方法,但我无法弄清楚。我发现很难解释我的问题,所以我希望我的描述清楚。

【问题讨论】:

确定你想用一个 Numpy 数组来做这个吗? Numpy 数组应该是统一的。恕我直言,您应该为此任务使用 Python 列表。 实际上可以这样使用数组,但是效率很低。整个问题听起来像是XY Problem。你想用这个子矩阵连接来达到什么目的? 实际上 3x4 数组是一种地图,我想将这些值存储在正确的“位置”上,以查看它们在每个位置是否或多或少相似。最后我想在每个单元格中取平均值,所以我只剩下一个 3x4 数组。 【参考方案1】:

测试这样一个数组是否有用的一种简单方法是将您的列表包装在np.array中:

In [767]: mat = np.array([[[1,8,9],[1,2],[],[]],
     ...: [[8],[],[4,5],[9,1]],
     ...: [[],[7,1,4],[],[2,1,3]]])
In [768]: mat
Out[768]: 
array([[list([1, 8, 9]), list([1, 2]), list([]), list([])],
       [list([8]), list([]), list([4, 5]), list([9, 1])],
       [list([]), list([7, 1, 4]), list([]), list([2, 1, 3])]], dtype=object)
In [769]: mat.shape
Out[769]: (3, 4)

结果是 (3,4) 对象 dtype 数组。这不是创建对象 dtype 数组的最可靠方法(以 np.empty((3,4),object) 开头更通用),但在这种情况下它可以正常工作。

但是这样的数组与原始列表相比并没有太多优势。大多数更快的数组操作都不起作用。大多数任务都需要对列表元素进行 Python 级迭代。

我可以使用np.vectorize 进行迭代,例如采取手段:

In [775]: np.vectorize(np.mean)(mat)
/usr/local/lib/python3.5/dist-packages/numpy/core/fromnumeric.py:2909: RuntimeWarning: Mean of empty slice.
  out=out, **kwargs)
/usr/local/lib/python3.5/dist-packages/numpy/core/_methods.py:80: RuntimeWarning: invalid value encountered in double_scalars
  ret = ret.dtype.type(ret / rcount)
Out[775]: 
array([[ 6. ,  1.5,  nan,  nan],
       [ 8. ,  nan,  4.5,  5. ],
       [ nan,  4. ,  nan,  2. ]])

它不喜欢取空列表的平均值。我们可以编写一个简单的函数来更优雅地处理[]

我可以把列表变成数组(注意otypes的使用):

In [777]: arr = np.vectorize(np.array,otypes=[object])(mat)
In [778]: arr
Out[778]: 
array([[array([1, 8, 9]), array([1, 2]), array([], dtype=float64),
        array([], dtype=float64)],
       [array([8]), array([], dtype=float64), array([4, 5]), array([9, 1])],
       [array([], dtype=float64), array([7, 1, 4]),
        array([], dtype=float64), array([2, 1, 3])]], dtype=object)

虽然我不确定这对我们有多大帮助。

【讨论】:

【参考方案2】:

您可以使用所谓的对象数组来完成这项工作。通常,numpy 数组由原始类型组成,但可以创建每个元素都是任意 Python 对象的数组。这样你就可以创建一个包含数组的数组。

mat = np.empty((3, 4), dtype=object)

请注意,mat 中的每个元素现在都是 None。让我们填充矩阵:

for x in range(1000):
    i, j, value = somefunction()
    if mat[i, j] is None:
        mat[i, j] = np.array(value)
    else:
        mat[i, j] = np.append(mat[i, j], value)

这应该可以完成工作,但它的效率非常低,原因有两个:

    dtype=object 几乎释放了所有使 numpy 数组快速的属性。对元素的每个操作都必须涉及 Python 解释器,这通常不会发生。 numpy 数组被设计成静态的;它们不是为了成长而设计的。所以np.append 真正做的是将旧数组复制到一个更大的新数组中。随着时间的推移,数组增长得越慢,这个速度就越慢。

考虑到您最终希望将整个事物缩减为 3x4 数组,使用常规 Python 列表可能会更好:

# initialize a 3x4x0 hierarchy of nested lists
mat = [[[] for _ in range(4)] for _ in range(3)]

for x in range(1000):
    i, j, value = somefunction()
    mat[i][j].append(value)

# reduce each sub-list to its mean (empty list -> nan)
for i in range(3):
    for j in range(4):
        mat[i][j] = np.mean(mat[i][j])

# FINALLY convert to array
mat = np.array(mat)

【讨论】:

以上是关于在二维数组中追加/连接数组的主要内容,如果未能解决你的问题,请参考以下文章

php一维数组如何追加到二维数组

有没有办法在没有numpy的情况下追加二维数组?

Java 数组 之 一维数组 追加 元素

java中二维数组和ArrayList的相互转换

请教一个关于二维数组的算法

jQuery写省级联动列表,创造二维数组,以及如何存/调用二维数组中的数据