Перемешать часть массива в NumPy - PullRequest
2 голосов
/ 12 марта 2019

У меня есть массив numpy, и я бы хотел перемешать его части. Например, со следующим массивом:

import numpy as np
import random

a = np.arange(15)
# => array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

Я хочу сделать:

shuffle_parts(a, [(0, 3), (10, 13)])
# => array([ 2,  0,  1,  3,  4,  5,  6,  7,  8,  9, 12, 11, 10, 13, 14])
#            ^^^^^^^^^                              ^^^^^^^^^^
#            Shuffle those 3 values                 and those 3 values

Следующее будет перетасовывать весь массив: (Не то, что я хочу)

random.shuffle(a) 
# => array([10, 11,  8,  1, 13,  5,  9, 14,  4,  7,  2, 12,  3,  0,  6])

Одним из способов будет использование разделения / объединения следующим образом:

splits = np.split(a, 5)
random.shuffle(splits[0])
random.shuffle(splits[3])
np.concatenate(splits)
# => array([ 2,  0,  1,  3,  4,  5,  6,  7,  8, 11, 10, 9, 12, 13, 14])
#            ^^^^^^^^^                          ^^^^^^^^^^
#            Correctly shuffled                 Shuffled but off by 1 index

Это почти то, что я хочу. Мои вопросы:

  • Могу ли я написать shuffle_parts, где индексы являются пользовательскими (детали с произвольными индексами, не ограниченные модулями, и детали с различной длиной)
  • Есть ли в numpy метод, который я пропустил и который помог бы мне сделать это?

Ответы [ 2 ]

2 голосов
/ 12 марта 2019

numpy срезы - это представления по данным ниже;так что вы можете напрямую перетасовать ломтики:

import numpy as np
import random

a = np.arange(15)

random.shuffle(a[0:3])
random.shuffle(a[10:13])
print(a)
# [ 2  0  1  3  4  5  6  7  8  9 12 10 11 13 14]

вы можете реализовать свою функцию shuffle_parts, используя slice таким образом:

def shuffle_parts(array, slices):
    for s in slices:
        random.shuffle(a[slice(*s)])

shuffle_parts(array=a, slices=((0, 3), (10, 13)))

или (в зависимости от того, как вы хотите передать фрагменты своей функции):

def shuffle_parts(array, slices):
    for s in slices:
        random.shuffle(a[s])

shuffle_parts(array=a, slices=(slice(0, 3), slice(10, 13)))

лично я бы предпочел вторую версию (таким образом, вы также можете, например, перетасовать четные индексы: shuffle_parts(array=a, slices=(slice(None, None, 2), ))) ...

2 голосов
/ 12 марта 2019

Это можно сделать напрямую:

>>> import numpy as np
>>> import random
>>> a = np.arange(15)
>>> s=3
>>> f=7
>>> random.shuffle(a[s:f])
>>> a
array([ 0,  1,  2,  5,  4,  3,  6,  7,  8,  9, 10, 11, 12, 13, 14])

Индексация напрямую ссылается на данные, делая это возможным.

...