Как дублировать строки в массиве Numpy на основе значения в каждой строке - PullRequest
1 голос
/ 16 мая 2019

Мне нужны дубликаты строк в массивах numpy, основанные на числовом значении первой записи в каждой строке.Поэтому, если значение равно 1, строка не дублируется, но если значение равно 3, эта строка будет представлена ​​3 раза.Я пытался использовать np.repeat и np.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 голосов
/ 16 мая 2019

Поскольку нет никакой гарантии, что ваши исходные 2D-массивы в исходном массиве 3D будут иметь одинаковую форму после выполнения этой операции, они, как правило, не могут быть объединены обратно в 3D-массив.

Вы можете получить list массивов с np.repeat, передав первый столбец каждого 2D-массива как количество повторений. Затем он будет повторять каждую строку соответствующее количество раз:

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]])]
0 голосов
/ 16 мая 2019

Используйте numpy.repeat с np.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]])]

Поскольку 2-мерные массивы не всегда имеют одинаковую форму, большую часть времени они выдают список массивов. Такое несоответствие не так хорошо обрабатывается numpy.

В этом случае вы можете просто использовать itertools.repeat с list пониманием. (Хотя это выглядит очень похоже на ответ @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]]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...