Ich möchte itertools.combinations für numpy implementieren. Basierend auf this discussion habe ich eine Funktion, die für 1D-Eingabe funktioniert:N-D-Version von iertools.combinations 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)
und der Ausgang macht Sinn:
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]])
wäre es jedoch am besten, wenn ich es ND-Eingänge erweitern könnte, wo Zusätzliche Dimensionen ermöglichen es Ihnen, schnell mehrere Anrufe gleichzeitig zu tätigen. Wenn also combs([1, 2, 3], 2)
[1, 2], [1, 3], [2, 3]
und combs([4, 5, 6], 2)
[4, 5], [4, 6], [5, 6]
produziert, dann sollte combs((1,2,3) and (4,5,6), 2)
[1, 2], [1, 3], [2, 3] and [4, 5], [4, 6], [5, 6]
produzieren, wobei "und" nur parallele Zeilen oder Spalten darstellt (was auch immer sinnvoll ist). (Und ebenso für zusätzliche Dimensionen)
Ich bin nicht sicher:
- Wie die Dimensionen in einer logischen Art und Weise arbeiten zu machen, die mit der Art und Weise andere Funktionen konsistent sind arbeiten (wie, wie einige numpy Funktionen ein
axis=
haben Parameter und ein Standard von Achse 0. Also sollte Achse 0 die sein, die ich kombiniere, und alle anderen Achsen nur Parallelrechnungen darstellen?) - Wie bekomme ich den obigen Code um mit ND zu arbeiten (gerade jetzt bekomme ich
ValueError: setting an array element with a sequence.
) - Gibt es eine bessere Möglichkeit,
dt = dtype([('', a.dtype)]*r)
zu tun?
So 'np.dtype ([('', np.intp)] * r)' ist die "richtige" Möglichkeit, eine Liste dtype zu erstellen? Ich habe es einfach erstochen, bis es geklappt hat. – endolith
Sehr cool! Ich fand, dass dies etwas weniger performant ist (sowohl in der Geschwindigkeit als auch im Gedächtnis), als die Lösung von @ HYRY, aber es ist immer noch besser als nur die Verwendung von itertools.combinations out-of-the-box. –