Vorrei implementare itertools.combinations per numpy. Sulla base di this discussion, ho una funzione che funziona per ingresso 1D:Versione N-D di itertools.combinazioni in numpy
def combs(a, r):
"""
Return successive r-length combinations of elements in the array a.
Should produce the same output as array(list(combinations(a, r))), but
faster.
"""
a = asarray(a)
dt = dtype([('', a.dtype)]*r)
b = fromiter(combinations(a, r), dt)
return b.view(a.dtype).reshape(-1, r)
e l'uscita senso:
In [1]: list(combinations([1,2,3], 2))
Out[1]: [(1, 2), (1, 3), (2, 3)]
In [2]: array(list(combinations([1,2,3], 2)))
Out[2]:
array([[1, 2],
[1, 3],
[2, 3]])
In [3]: combs([1,2,3], 2)
Out[3]:
array([[1, 2],
[1, 3],
[2, 3]])
tuttavia, sarebbe meglio se ho potuto espandersi a ingressi ND, dove le dimensioni aggiuntive ti consentono semplicemente di eseguire più chiamate contemporaneamente in modo rapido. Quindi, concettualmente, se combs([1, 2, 3], 2)
produce [1, 2], [1, 3], [2, 3]
e combs([4, 5, 6], 2)
produce [4, 5], [4, 6], [5, 6]
, quindi combs((1,2,3) and (4,5,6), 2)
dovrebbe produrre [1, 2], [1, 3], [2, 3] and [4, 5], [4, 6], [5, 6]
dove "e" rappresenta solo righe o colonne parallele (a seconda del caso). (E allo stesso modo per ulteriori dimensioni)
non sono sicuro:
- Come rendere le dimensioni funzionano in modo logico che è coerente con il modo in cui le altre funzioni funzionano (come come alcune funzioni NumPy hanno un
axis=
parametro e un valore predefinito dell'asse 0. Quindi probabilmente l'asse 0 dovrebbe essere quello che sto combinando e tutti gli altri assi rappresentano solo calcoli paralleli?) - Come ottenere il codice sopra per lavorare con ND (in questo momento ricevo
ValueError: setting an array element with a sequence.
) - C'è un modo migliore per fare
dt = dtype([('', a.dtype)]*r)
?
Quindi 'np.dtype ([('', np.intp)] * r)' è il modo "giusto" per creare un elenco dtype? L'ho solo pugnalato finché non ha funzionato. – endolith
Molto bello! Ho trovato che questo è leggermente meno performante (sia in velocità che in memoria) rispetto alla soluzione di @ HYRY, ma è comunque meglio che usare itertools.combinations out of the box. –