webentwicklung-frage-antwort-db.com.de

Wie erstelle ich ein mehrdimensionales Numpy-Array mit variierender Zeilengröße?

Ich möchte ein zweidimensionales numpy-Array von Arrays erstellen, das eine unterschiedliche Anzahl von Elementen in jeder Zeile enthält.

Ich versuche es

cells = numpy.array([[0,1,2,3], [2,3,4]])

gibt einen Fehler

ValueError: setting an array element with a sequence.
48
dzhelil

Während Numpy über Arrays beliebiger Objekte Bescheid weiß, ist es für homogene Arrays von Zahlen mit festen Dimensionen optimiert. Wenn Sie wirklich Arrays von Arrays benötigen, verwenden Sie besser eine verschachtelte Liste. Abhängig von der beabsichtigten Verwendung Ihrer Daten können jedoch unterschiedliche Datenstrukturen noch besser sein, z. Ein maskiertes Array, wenn Sie ungültige Datenpunkte haben.

Wenn Sie wirklich flexible Numpy-Arrays wünschen, verwenden Sie Folgendes:

numpy.array([[0,1,2,3], [2,3,4]], dtype=object)

Dadurch wird jedoch ein eindimensionales Array erstellt, in dem Verweise auf Listen gespeichert werden. Dies bedeutet, dass Sie die meisten Vorteile von Numpy (Vektorverarbeitung, Lokalität, Slicing usw.) verlieren.

24
Philipp

Wir sind jetzt fast 7 Jahre nach der Frage und Ihrem Code

cells = numpy.array([[0,1,2,3], [2,3,4]])

in numpy 1.12.0 ausgeführt, python 3.5, erzeugt keinen Fehler und cells enthält:

array([[0, 1, 2, 3], [2, 3, 4]], dtype=object)

Sie greifen auf Ihre cells Elemente als cells[0][2] # (=2) zu.

Eine Alternative zu Tom10s Lösung , wenn Sie Ihre Liste von Numpy-Arrays im laufenden Betrieb erstellen möchten, sobald neue Elemente (d. H. Arrays) verfügbar werden, ist die Verwendung von append:

d = []                 # initialize an empty list
a = np.arange(3)       # array([0, 1, 2])
d.append(a)            # [array([0, 1, 2])]
b = np.arange(3,-1,-1) #array([3, 2, 1, 0])
d.append(b)            #[array([0, 1, 2]), array([3, 2, 1, 0])]
24
calocedrus

Dies wird in Numpy nicht gut unterstützt (per Definition hat ein "zweidimensionales Array" fast überall alle Zeilen gleicher Länge). Eine Python Liste von Numpy-Arrays kann eine gute Lösung für Sie sein, da Sie auf diese Weise die Vorteile von Numpy erhalten, wo Sie sie verwenden können:

cells = [numpy.array(a) for a in [[0,1,2,3], [2,3,4]]]
12
tom10

Eine andere Möglichkeit wäre, Ihre Arrays als ein zusammenhängendes Array zu speichern und auch ihre Größen oder Offsets zu speichern. Dies erfordert etwas mehr konzeptionelle Überlegungen zur Bedienung Ihrer Arrays, aber es kann eine überraschend große Anzahl von Vorgängen ausgeführt werden, als ob Sie ein zweidimensionales Array mit unterschiedlichen Größen hätten. In den Fällen, in denen sie nicht können, dann np.split kann verwendet werden, um die von Calocedrus empfohlene Liste zu erstellen. Die einfachsten Operationen sind Ufuncs, da sie fast keine Modifikation erfordern. Hier sind einige Beispiele:

cells_flat = numpy.array([0, 1, 2, 3, 2, 3, 4])
# One of these is required, it's pretty easy to convert between them,
# but having both makes the examples easy
cell_lengths = numpy.array([4, 3])
cell_starts = numpy.insert(cell_lengths[:-1].cumsum(), 0, 0)
cell_lengths2 = numpy.diff(numpy.append(cell_starts, cells_flat.size))
assert np.all(cell_lengths == cell_lengths2)

# Copy prevents shared memory
cells = numpy.split(cells_flat.copy(), cell_starts[1:])
# [array([0, 1, 2, 3]), array([2, 3, 4])]

numpy.array([x.sum() for x in cells])
# array([6, 9])
numpy.add.reduceat(cells_flat, cell_starts)
# array([6, 9])

[a + v for a, v in Zip(cells, [1, 3])]
# [array([1, 2, 3, 4]), array([5, 6, 7])]
cells_flat + numpy.repeat([1, 3], cell_lengths)
# array([1, 2, 3, 4, 5, 6, 7])

[a.astype(float) / a.sum() for a in cells]
# [array([ 0.        ,  0.16666667,  0.33333333,  0.5       ]),
#  array([ 0.22222222,  0.33333333,  0.44444444])]
cells_flat.astype(float) / np.add.reduceat(cells_flat, cell_starts).repeat(cell_lengths)
# array([ 0.        ,  0.16666667,  0.33333333,  0.5       ,  0.22222222,
#         0.33333333,  0.44444444])

def complex_modify(array):
    """Some complicated function that modifies array

    pretend this is more complex than it is"""
    array *= 3

for arr in cells:
    complex_modify(arr)
cells
# [array([0, 3, 6, 9]), array([ 6,  9, 12])]
for arr in numpy.split(cells_flat, cell_starts[1:]):
    complex_modify(arr)
cells_flat
# array([ 0,  3,  6,  9,  6,  9, 12])
2
Erik

In numpy 1.14.3 mit append:

d = []                 # initialize an empty list
a = np.arange(3)       # array([0, 1, 2])
d.append(a)            # [array([0, 1, 2])]
b = np.arange(3,-1,-1) #array([3, 2, 1, 0])
d.append(b)            #[array([0, 1, 2]), array([3, 2, 1, 0])]

was Sie erhalten eine Liste von Arrays (die unterschiedlich lang sein können) und Sie können Operationen wie d[0].mean() ausführen. Andererseits,

cells = numpy.array([[0,1,2,3], [2,3,4]])

führt zu einer Reihe von Listen.

Möglicherweise möchten Sie dies tun:

a1 = np.array([1,2,3])
a2 = np.array([3,4])
a3 = np.array([a1,a2])
a3 # array([array([1, 2, 3]), array([3, 4])], dtype=object)
type(a3) # numpy.ndarray
type(a2) # numpy.ndarray