Выберите клетки случайным образом из Numpy Array - без замены

StackOverflow https://stackoverflow.com/questions/3891180

Вопрос

Я пишу несколько процедуров моделирования в NUMPY, который должен случайным образом выбирать ячейки из Numpy Array и выполнять некоторую обработку на них. Все клетки должны быть выбраны без замены (как в, после того, как ячейка была выбрана, она не может быть выбрана снова, но все клетки должны быть выбраны к концу).

Я перехожу с IDL, где я могу найти хороший способ сделать это, но я предполагаю, что Numpy имеет хороший способ сделать это тоже. Что ты предлагаешь?

Обновлять: Я должен был заявить, что я пытаюсь сделать это на 2D-массивах, и поэтому получить набор из 2D-индексов.

Это было полезно?

Решение

Как насчет использования numpy.random.shuffle или numpy.random.permutation Если вам все еще нужен оригинальный массив?

Если вам нужно изменить настроек массива, чем вы можете создать индексный массив, как это:

your_array = <some numpy array>
index_array = numpy.arange(your_array.size)
numpy.random.shuffle(index_array)

print your_array[index_array[:10]]

Другие советы

Все эти ответы казались немного запутанными для меня.

Я предполагаю, что у вас есть многомерный массив, из которого вы хотите создать исчерпывающий список индексов. Вы хотели бы, чтобы эти индексы перетасовали, чтобы вы могли получить доступ к каждому из элементов массива в случайном порядке.

Следующий код сделает это простым и прямым способом:

#!/usr/bin/python
import numpy as np

#Define a two-dimensional array
#Use any number of dimensions, and dimensions of any size
d=numpy.zeros(30).reshape((5,6))

#Get a list of indices for an array of this shape
indices=list(np.ndindex(d.shape))

#Shuffle the indices in-place
np.random.shuffle(indices)

#Access array elements using the indices to do cool stuff
for i in indices:
  d[i]=5

print d

Печать d Проверено, что все элементы доступны.

Обратите внимание, что массив может иметь любое количество измерений и что размеры могут быть любого размера.

Единственный недостаток этого подхода заключается в том, что если d большой, то indices может стать довольно значительным. Поэтому было бы неплохо иметь генератор. Отказ К сожалению, я не могу думать о том, как построить перетасованный итератор.

Расширение приятного ответа от @Вольф

Для 2D-массива, я думаю, что это будет зависеть от того, что вы хотите или нужно знать о показателях.

Вы могли бы сделать что-то вроде этого:

data = np.arange(25).reshape((5,5))

x, y  = np.where( a = a)
idx = zip(x,y)
np.random.shuffle(idx)

ИЛИ

data = np.arange(25).reshape((5,5))

grid = np.indices(data.shape)
idx = zip( grid[0].ravel(), grid[1].ravel() )
np.random.shuffle(idx)

Вы можете использовать список idx Для случаев повторяется случайным образом заказанные показатели 2D массива, как вы хотите, и получить значения в этом индексе из data который остается без изменений.

Примечание: Вы также можете генерировать случайно заказанные индексы через itertools.product ТОО, если вам удобнее с этим набором инструментов.

Использовать random.sample Для генерирования INT в 0 .. a.size без дубликатов, затем разделить их на проводные пары:

import random
import numpy as np

def randint2_nodup( nsample, A ):
    """ uniform int pairs, no dups:
        r = randint2_nodup( nsample, A )
        A[r]
        for jk in zip(*r):
            ... A[jk]
    """
    assert A.ndim == 2
    sample = np.array( random.sample( xrange( A.size ), nsample ))  # nodup ints
    return sample // A.shape[1], sample % A.shape[1]  # pairs


if __name__ == "__main__":
    import sys

    nsample = 8
    ncol = 5
    exec "\n".join( sys.argv[1:] )  # run this.py N= ...
    A = np.arange( 0, 2*ncol ).reshape((2,ncol))

    r = randint2_nodup( nsample, A )
    print "r:", r
    print "A[r]:", A[r]
    for jk in zip(*r):
        print jk, A[jk]

Допустим, у вас есть массив точек данных размером 8x3

data = np.arange(50,74).reshape(8,-1)

Если вы действительно хотите попробовать, как вы говорите, все индексы как 2D-пары, самый компактный способ сделать это, что я могу думать, это:

#generate a permutation of data's size, coerced to data's shape
idxs = divmod(np.random.permutation(data.size),data.shape[1])

#iterate over it
for x,y in zip(*idxs): 
    #do something to data[x,y] here
    pass

МЧС вообще, однако, один часто не нужно получать доступ к 2D-массивам в качестве 2D-массива просто для перемещения их, в этом случае можно еще более компактно. Просто сделайте 1D View на массив и сэкономьте себе какой-то индекс.

flat_data = data.ravel()
flat_idxs = np.random.permutation(flat_data.size)
for i in flat_idxs:
    #do something to flat_data[i] here
    pass

Это все равно будет запустить 2D «оригинальный» массив, который хотелось бы. Чтобы увидеть это, попробуйте:

 flat_data[12] = 1000000
 print data[4,0]
 #returns 1000000

люди, использующие Numpy версии 1.7 или более поздней версии, могут также использовать встроенную функцию numpy.random.choice

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top