2013-10-13 5 views
0

У меня есть массив 41000x3 numpy, который я называю «отсортированным списком» в приведенной ниже функции. В третьем столбце есть куча значений, некоторые из которых являются дубликатами, а другие - нет. Я хотел бы взять образец уникальных значений (без дубликатов) из третьего столбца, который является отсортированным списком [:, 2]. Я думаю, что я могу сделать это легко с помощью numpy.random.sample (sortedlist [:, 2], sample_size). Проблема в том, что я хотел бы вернуть не только эти значения, но и все три столбца, где в последнем столбце есть случайные значения, которые я получаю из numpy.random.sample.Выбор уникальных случайных значений из третьего столбца массива в python

EDIT: По уникальным значениям я имею в виду, что я хочу выбрать случайные значения, которые появляются только один раз. Так что если у меня был массив:

array = [[0, 6, 2] 
     [5, 3, 9] 
     [3, 7, 1] 
     [5, 3, 2] 
     [3, 1, 1] 
     [5, 2, 8]] 

И я хотел выбрать 4 значения третьего столбца, я хочу, чтобы получить что-то вроде new_array_1 из:

new_array_1 = [[5, 3, 9] 
       [3, 7, 1] 
       [5, 3, 2] 
       [5, 2, 8]] 

Но я не хочу что-то вроде new_array_2, где два значения в 3-м столбце одинаковы:

new_array_2 = [[5, 3, 9] 
       [3, 7, 1] 
       [5, 3, 2] 
       [3, 1, 1]] 

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

samplesize = 100 

rand_sortedlist = sortedlist[np.random.randint(len(sortedlist), size = sample_size),:]] 

Я пытаюсь применять этот критерий, делая что-то вроде этого

array_index = where(array[:,2] == sample(SelectionWeight, sample_size)) 

Но я не уверен, если я нахожусь на правильном пути. Любая помощь будет принята с благодарностью!

+1

Я не уверен, что вы имеете в виду, когда говорите: «Я хотел бы взять образец уникальных значений ** (без дубликатов) **». Вы хотите исключить любые значения из выборки, если они появляются более одного раза? Или вы хотите выбрать из списка, в котором все элементы уникальны? Или вы хотите попробовать без замены, так что случайные выборки никогда не дублируются? Или какая-то комбинация? Некоторые примеры данных помогут. – Brionius

+0

Включает ли третий столбец все числа от 0 или 1 до максимума, с некоторыми дубликатами, или есть пробелы в последовательности? –

ответ

0

Я не могу придумать умный способ numpythonic для этого, который не включает в себя несколько проходов над данными. (Иногда NumPy намного быстрее, чем чистый Python, который по-прежнему самый быстрый путь, но он никогда не чувствует себя хорошо.)

В чистом Python, я хотел бы сделать что-то вроде

def draw_unique(vec, n): 
    # group indices by value 
    d = {} 
    for i, x in enumerate(vec): 
     d.setdefault(x, []).append(i) 

    drawn = [random.choice(d[k]) for k in random.sample(d, n)]   
    return drawn 

, который дал бы

>>> a = np.random.randint(0, 10, (41000, 3)) 
>>> drawn = draw_unique(a[:,2], 3) 
>>> drawn 
[4219, 6745, 25670] 
>>> a[drawn] 
array([[5, 6, 0], 
     [8, 8, 1], 
     [5, 8, 3]]) 

я могу думать о некоторых трюках с np.bincount и scipy.stats.rankdata, но они болеют мой голова, и там всегда будет завершаться быть один шагом в конце концов, я не могу видеть, как векторизации .. и если я не векторизации все, что я мог бы использовать выше который по крайней мере прост.

0

Я считаю, что это сделает то, что вы хотите. Обратите внимание, что на время работы почти наверняка будет доминировать любой метод, который вы используете для генерации ваших случайных чисел. (Исключением является то, что набор данных является гигантским, но вам нужно только небольшое количество строк, и в этом случае очень мало случайных чисел нужно рисовать.) Поэтому я не уверен, что это будет работать намного быстрее, чем чистый метод python.

# arrayify your list of lists 
# please don't use `array` as a variable name! 
a = np.asarray(arry) 

# sort the list ... always the first step for efficiency 
a2 = a[np.argsort(a[:, 2])] 

# identify rows that are duplicates (3rd column is non-increasing) 
# Note this has length one less than a2 
duplicate_rows = np.diff(a2[:, 2]) == 0) 

# if duplicate_rows[N], then we want to remove row N and N+1 
keep_mask = np.ones(length(a2), dtype=np.bool) # all True 
keep_mask[duplicate_rows] = 0 # remove row N 
keep_mask[1:][duplicate_rows] = 0 # remove row N + 1 

# now actually slice the array 
a3 = a2[keep_mask] 

# select rows from a3 using your preferred random number generator 
# I actually prefer `random` over numpy.random for sampling w/o replacement 
import random 
result = a3[random.sample(xrange(len(a3)), DESIRED_NUMBER_OF_ROWS)] 
Смежные вопросы