如何根据每行中的值复制numpy数组中的行

时间:2019-05-16 02:07:47

标签: python arrays numpy

我希望基于每行中第一项的数值在numpy数组中重复行。因此,如果值为1,则不会重复该行,但是如果值为3,则该行将被表示3次。我尝试使用np.repeatnp.tile,但我不知道它们是否是正确的工具,我还不确定是否有办法。

这是我随机生成的数组:

[[[3 1 3 1 2]
  [4 4 4 2 0]
  [3 4 4 4 0]
  [1 4 3 3 0]]

 [[4 2 0 2 1]
  [2 1 2 0 3]
  [4 1 3 4 3]
  [2 3 2 0 0]]]

我的目标是最终做到这一点:

[[[3 1 3 1 2]
  [3 1 3 1 2]
  [3 1 3 1 2]
  [4 4 4 2 0]
  [4 4 4 2 0]
  [4 4 4 2 0]
  [4 4 4 2 0]
  [3 4 4 4 0]
  [3 4 4 4 0]
  [3 4 4 4 0]
  [1 4 3 3 0]]

 [[4 2 0 2 1]
  [4 2 0 2 1]
  [4 2 0 2 1]
  [4 2 0 2 1]
  [2 1 2 0 3]
  [2 1 2 0 3]
  [4 1 3 4 3]
  [4 1 3 4 3]
  [4 1 3 4 3]
  [4 1 3 4 3]
  [2 3 2 0 0]
  [2 3 2 0 0]]]

这是我到目前为止的代码

array = np.random.randint(5, size = (2, 4,5))

for a in array:
    for b in a:
        array = np.tile(a, (b[0],1))

如果我打印b[0],则可以获得每个值。我想使用这些值来复制每一行。

3
4
3
1
4
2
4
2

所以我认为我可以遍历这些值,并将每行乘以其相应的值以添加新行,但是我的结果只复制第二个数组一次。

[[4 2 0 2 1]
 [2 1 2 0 3]
 [4 1 3 4 3]
 [2 3 2 0 0]
 [4 2 0 2 1]
 [2 1 2 0 3]
 [4 1 3 4 3]
 [2 3 2 0 0]]

我要去哪里错了?我不应该使用np.tile吗?

2 个答案:

答案 0 :(得分:0)

numpy.repeatnp.arange一起使用:

import numpy as np

    arr = np.array([[[3, 1, 3, 1, 2],
  [4, 4, 4, 2, 0],
  [3, 4, 4, 4, 0],
  [1, 4, 3, 3, 0]],
 [[4, 2, 0, 2, 1],
  [2, 1, 2, 0, 3],
  [4, 1, 3, 4, 3],
  [2, 3, 2, 0, 0]]])

arr2d = np.vstack(arr)
dup = arr2d[np.repeat(np.arange(arr2d.shape[0]), arr2d[:,0])]
np.split(dup, np.cumsum(np.sum(np.split(arr2d[:,0], arr.shape[0]), 1)))[:-1]

输出:

[array([[3, 1, 3, 1, 2],
        [3, 1, 3, 1, 2],
        [3, 1, 3, 1, 2],
        [4, 4, 4, 2, 0],
        [4, 4, 4, 2, 0],
        [4, 4, 4, 2, 0],
        [4, 4, 4, 2, 0],
        [3, 4, 4, 4, 0],
        [3, 4, 4, 4, 0],
        [3, 4, 4, 4, 0],
        [1, 4, 3, 3, 0]]), 
 array([[4, 2, 0, 2, 1],
        [4, 2, 0, 2, 1],
        [4, 2, 0, 2, 1],
        [4, 2, 0, 2, 1],
        [2, 1, 2, 0, 3],
        [2, 1, 2, 0, 3],
        [4, 1, 3, 4, 3],
        [4, 1, 3, 4, 3],
        [4, 1, 3, 4, 3],
        [4, 1, 3, 4, 3],
        [2, 3, 2, 0, 0],
        [2, 3, 2, 0, 0]])]

由于二维数组并不总是具有相同的形状,因此大多数情况下它将产生数组列表。 numpy不能很好地处理这种不一致情况。

在这种情况下,您可以将itertools.repeatlist一起使用。 (尽管它看起来与@gmds的答案非常相似)

给出l

import itertools

l = [[[3, 1, 3, 1, 2], [4, 4, 4, 2, 0], [3, 4, 4, 4, 0], [1, 4, 3, 3, 0]],
 [[4, 2, 0, 2, 1], [2, 1, 2, 0, 3], [4, 1, 3, 4, 3], [2, 3, 2, 0, 0]]]

[[j for i in sub for j in itertools.repeat(i, i[0])] for sub in l]

输出:

[[[3, 1, 3, 1, 2],
  [3, 1, 3, 1, 2],
  [3, 1, 3, 1, 2],
  [4, 4, 4, 2, 0],
  [4, 4, 4, 2, 0],
  [4, 4, 4, 2, 0],
  [4, 4, 4, 2, 0],
  [3, 4, 4, 4, 0],
  [3, 4, 4, 4, 0],
  [3, 4, 4, 4, 0],
  [1, 4, 3, 3, 0]],
 [[4, 2, 0, 2, 1],
  [4, 2, 0, 2, 1],
  [4, 2, 0, 2, 1],
  [4, 2, 0, 2, 1],
  [2, 1, 2, 0, 3],
  [2, 1, 2, 0, 3],
  [4, 1, 3, 4, 3],
  [4, 1, 3, 4, 3],
  [4, 1, 3, 4, 3],
  [4, 1, 3, 4, 3],
  [2, 3, 2, 0, 0],
  [2, 3, 2, 0, 0]]]

答案 1 :(得分:0)

由于不能保证执行此操作后3D源阵列中的原始2D子阵列将具有相同的形状,因此通常不能将它们堆叠回3D阵列中。

通过将每个2D数组的第一列作为重复次数传递,可以使用list获得np.repeat数组。然后,它将每行重复相应的次数:

from pprint import pprint

result = ([np.repeat(a[i], a[i, :, 0], axis=0) for i in range(a.shape[0])])

pprint(result)

输出:

[array([[3, 1, 3, 1, 2],
       [3, 1, 3, 1, 2],
       [3, 1, 3, 1, 2],
       [4, 4, 4, 2, 0],
       [4, 4, 4, 2, 0],
       [4, 4, 4, 2, 0],
       [4, 4, 4, 2, 0],
       [3, 4, 4, 4, 0],
       [3, 4, 4, 4, 0],
       [3, 4, 4, 4, 0],
       [1, 4, 3, 3, 0]]),
 array([[4, 2, 0, 2, 1],
       [4, 2, 0, 2, 1],
       [4, 2, 0, 2, 1],
       [4, 2, 0, 2, 1],
       [2, 1, 2, 0, 3],
       [2, 1, 2, 0, 3],
       [4, 1, 3, 4, 3],
       [4, 1, 3, 4, 3],
       [4, 1, 3, 4, 3],
       [4, 1, 3, 4, 3],
       [2, 3, 2, 0, 0],
       [2, 3, 2, 0, 0]])]