2014-09-29 2 views
1

Каков хороший способ получить комбинации индексов, которые указывают на уникальные элементы массива. Например, a = [1,1,3,2], возможный набор указателей будет {0,2,3}, {1,2,3}.Декартовы продукты, чтобы получить набор индексов для указания на уникальные элементы в массиве NumPy

Я могу использовать argsort в сочетании с расщеплением элементов по частоте, чтобы затем использовать что-то вроде itertools.product, чтобы получить все наборы индексов, которые я хочу.

Это то, что я пробовал:

from numpy import array, split 
from scipy.stats import itemfreq 
from itertools import product 
a = array([1,1,3,2]) 
fq = itemfreq(a)[:,1] 
fq = [int(f + sum(fq[:i])) for i, f in enumerate(fq)] 
print list(product(*(ptrs for ptrs in split(a.argsort(), fq) if len(ptrs)))) 
#> [(0, 3, 2), (1, 3, 2)] 

Как я могу сделать это лучше?

+2

На личном уровне используйте 'from numpy import array, split' вместо' from pylab import * '. – Veedrac

ответ

3

Это получит Вас показатели, но, возможно, не в формате, который вы хотите:

[np.where(a==x) for x in np.unique(a)] 

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

Я полагаю, что есть лучший способ, без цикла.

+3

Спасибо, это лучше, чем у меня, возможно, это может быть как-то улучшено, я могу получить формат, который я хочу, используя это: 'print list (product (* (np.where (a == x) [0] для x в np.unique (a)))) ' – Joelmob

+2

@Joelmob: Этот ответ в сочетании с вашим предложенным правлением - это то, что я имел в своем ответе, но основная идея здесь такая же, как у меня, поэтому я удалил свой ответ. –

+0

Хорошо спасибо @Warren. Это было то же самое, но короче: 'list (product (* (a [a == x] для x в np.unique (a)))) – Joelmob

1

Ответ @ atomh33ls может быть векторизован следующим образом.

Сначала извлеките инверсные индексы и подсчеты каждого уникального элемента. Если вы используете NumPy> = 1.9:

_, idx, cnt = np.unique(a, return_inverse=True, return_counts=True) 

В старых версиях это делает то же самое:

_, idx = np.unique(a, return_inverse=True) 
cnt = np.bincount(idx) 

А теперь, немного магии и, вуаля:

>>> np.split(np.arange(len(a))[np.argsort(idx)], np.cumsum(cnt)[:-1]) 
[array([0, 1]), array([3]), array([2])]