2017-01-12 9 views
2

Ich habe die folgende Liste von verschiedenen numpy Arrays:Python: Iterieren durch jedes Element innerhalb der parallelen verschachtelten Listen

nparrays_list = [ 
    array([1, 2, 3, 4]) 
    array([5, 6, 7, 8]), 
    array([9, 10, 11, 12]) 
] 

Ich möchte durch die gesamte Liste zu durchlaufen, ohne die Form der Liste zu beeinflussen (dh I don‘ t wollen, um die Liste abflachen) die folgende Liste von numpy Arrays zu erhalten:

nparrays_list_Decimal = [ 
    array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')]) 
    array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')]), 
    array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')]) 
] 

Hier ist der Code, den ich habe bisher:

import numpy as np 

nparrays_list_Decimal = [] 
for nparray in nparrays_list: 
    nparray_Decimal = np.array([D(str(item)) for item in nparray]) 
    nparrays_list_Decimal.append(nparray_Decimal) 

Mein Problem ist, ich habe es mit einer Menge Daten zu tun, also ist das Erstellen einer neuen Liste nicht ideal (d. H. verschwendeter Speicher). Gibt es eine einfache Möglichkeit, jedes Element in der ursprünglichen Liste zu durchlaufen, selbst wenn sich die Elemente in verschachtelten Listen (oder in diesem Fall numy Arrays) befinden?

+1

Wie haben Sie das 'D' definiert? Und warum 'nparrays_list' ist kein numpy Array? – Kasramvd

+0

Ich denke, Sie könnten zumindest die temporäre Liste speichern, indem Sie ein "

+0

'D' steht für Dezimal. Lass mich das bearbeiten, um es klarer zu machen. Und es ist 'nparrays_list', weil es eine Liste von numpy Arrays ist. Ich brauche den Container auch nicht, um ein Nparray zu sein –

Antwort

1

Da Sie eine diffe haben mieten Objekttyp innerhalb des Numpy Array, müssen Sie neue Arrays erstellen (es sei denn, sie Anordnungen von dtype=object sind)

Hier ist eine Demo von der Tatsache ist, dass Sie nicht Mischtypen in einem Numpy Array haben:

>>> arr=np.array([1,2,3]) 
>>> arr 
array([1, 2, 3]) 
>>> arr[1]="string" 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: invalid literal for long() with base 10: 'string' 

Das Zuweisen eines Decimal-Typs zu einem Array von Ints ändert dieses Element nicht in einen Dezimaltyp im Array. arr[1] in eine Decimal umgewandelt, aber dann in einen int umgewandelt zurück still:

>>> arr 
array([1, 2, 3]) 
>>> arr[1]=Decimal(arr[1]) 
>>> arr 
array([1, 2, 3]) 
>>> type(arr[1]) 
<type 'numpy.int64'> 

Sie tun können:

>>> nparrays_list_Decimal=[np.array([Decimal(e) for e in arr]) for arr in nparrays_list] 
>>> nparrays_list_Decimal 
[array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], dtype=object), array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], dtype=object), array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')], dtype=object)] 

Oder nur mit einer Liste der Listen-Stick:

>>> LoL=[[Decimal(e) for e in arr] for arr in nparrays_list] 
>>> LoL 
[[Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], [Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], [Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')]] 

Wenn Speicher Ihr Anliegen ist, (a nd in die Regel brauchen Sie nicht so viele Sorgen zu machen mit bescheidener Arrays) Sie können effiziente Umwandlung einen Speicher tun, indem Sie den Sub-Arrays zu löschen, wie Sie sie konvertieren:

from collections import deque 

nparrays_list=deque(LoA) # the List of Arrays is garbage collected.. 
nparrays_list_Decimal=[] 
while nparrays_list: 
    # each sublist is garbage collected after being popped and iterated 
    nparrays_list_Decimal.append(np.array([Decimal(e) for e in nparrays_list.popleft()])) 

>>> nparrays_list_Decimal 
[array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], dtype=object), array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], dtype=object), array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')], dtype=object)] 
+0

Das Listenverständnis ist ausreichend. Vielen Dank. Und basierend auf deinem Beitrag und dem Beitrag von hpaulj klingt es so, als wäre die Erinnerung hier kein limitierender Faktor. –

0

Um über jedes Element zu iterieren, können Sie eine geschachtelte for-Schleife wie folgt machen.

nparrays_list = [ 
     array([1, 2, 3, 4]), 
     array([5, 6, 7, 8]), 
     array([9, 10, 11, 12]) 
    ] 

for arr in nparrays_list: 
    for i, item in enumerate(arr): 
    arr[i] = Decimal(str(item)) 
+0

Wenn ich 'item = Decimal (str (item))' auf der letzten Zeile versuche, passiert nichts. Wie kann ich damit alle Werte in Dezimalobjekte umwandeln? –

+0

@ jcmetz21 Aktualisiert meine Antwort auf diese – gipsy

+0

Dies konvertiert die Elemente nicht in 'Decimal' Objekte. Siehe den Beitrag von hpaulj oder meinen Beitrag. – dawg

1

Vielleicht so etwas wie dieses

import numpy as np 

nparrays_list_Decimal = [list(map(float, lst)) for lst in nparrays_list] 

Edit:

From the Python Documentation on Decimals

Dezimalzahlen dieses

versuchen zu verwenden
from decimal import * 
nparrays_list_Decimal = [list(map(Decimal, lst)) for lst in nparrays_list] 
+0

Wie kann ich das verwenden, um die Zahlen in Dezimal-Objekte zu konvertieren (die ich für größere Genauigkeit benötige)? Floats sind zu ungenau –

+1

Der Dezimalcode wurde für Sie hinzugefügt –

1
nparrays_list = [ 
    array([1, 2, 3, 4]) 
    array([5, 6, 7, 8]), 
    array([9, 10, 11, 12]) 
] 

Keine Sorge darum, neue Listen. Listen enthalten nur Zeiger auf Objekte im Speicher. In diesem Fall belegt die Liste nur den Speicher von 3 ganzen Zahlen. Die Komponenten belegen Speicher - sie sind Arrays mit 4 Element-Datenpuffern.

nparrays_list_Decimal = [ 
    array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')]), 
    array([Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')]), 
    array([Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')]) 
] 

ist eine andere kleine Liste, mit 3 Zeigern. Sie könnten diese Zeiger wieder auf das Original nparray_list setzen, aber warum? Nur um 3 ganzen Platz zu sparen?

Aber was bedeutsam ist, dass die neuen Arrays nicht kompatibel sind, Speicher klug, mit den Originalen:

array([Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')]) 

ein Objekt dtype Array ist. Das ist wie eine Liste, mit Zeigern auf diese Decimal(n') Objekte wo sonst im Speicher. Das muss ein neues Array sein; es kann die np.int32 Einzelteile im ursprünglichen array([1,2,3,4]) nicht ersetzen.

Warum gehst du nicht einfach aus

nparrays_list = [ 
    [1, 2, 3, 4], 
    [5, 6, 7, 8], 
    [9, 10, 11, 12] 
] 

zu:

nparrays_list_Decimal = [ 
    [Decimal('1'), Decimal('2'), Decimal('3'), Decimal('4')], 
    [Decimal('5'), Decimal('6'), Decimal('7'), Decimal('8')], 
    [Decimal('9'), Decimal('10'), Decimal('11'), Decimal('12')] 
] 

Mit anderen Worten, Stick mit Listen von Listen. Ist ein Array von Decimal Objekten nützlicher als eine Liste derselben?

===============

Decimal Da viele mathematische Operationen definiert, es ist möglich, einige mathematische Array auf einer Anordnung von Objekten Decimal auszuführen:

In [482]: arr = np.array([Decimal(i) for i in range(1,4)]) 
In [483]: arr 
Out[483]: array([Decimal('1'), Decimal('2'), Decimal('3')], dtype=object) 
In [484]: arr + 1 
Out[484]: array([Decimal('2'), Decimal('3'), Decimal('4')], dtype=object) 
In [485]: 1/arr 
Out[485]: 
array([Decimal('1'), Decimal('0.5'), 
     Decimal('0.3333333333333333333333333333')], dtype=object) 

speedwise diese letzte Aussage ist grundsätzlich das gleiche wie:

np.array([1/i for i in arr]) 

Es langsamer als 1/np.arange(1,4) sein wird.

====================

Sie könnten ein wenig Verbesserung der Geschwindigkeit erhalten, indem die Dezimal-Array machen mit:

In [503]: np.frompyfunc(Decimal,1,1)(np.arange(3)) 
Out[503]: array([Decimal('0'), Decimal('1'), Decimal('2')], dtype=object) 
In [504]: np.frompyfunc(Decimal,1,1)(np.arange(12).reshape(3,4)) 
Out[504]: 
array([[Decimal('0'), Decimal('1'), Decimal('2'), Decimal('3')], 
     [Decimal('4'), Decimal('5'), Decimal('6'), Decimal('7')], 
     [Decimal('8'), Decimal('9'), Decimal('10'), Decimal('11')]], dtype=object) 

In andere Tests habe ich gefunden, dass frompyfunc eine bescheidene (zB 2x) Geschwindigkeit Verbesserung gegenüber expliziter Iteration Ausdrücke hat. Es hat auch den Vorteil, nahtlos mit mehrdimensionalen Arrays umzugehen. Es gibt ein Array object zurück. Manchmal ist das ein Problem. Hier ist das in Ordnung.

In [509]: timeit np.frompyfunc(Decimal,1,1)(np.arange(2000)) 
1000 loops, best of 3: 752 µs per loop 
In [510]: timeit np.array([Decimal(str(i)) for i in np.arange(2000)]) 
100 loops, best of 3: 17.1 ms per loop 
In [515]: timeit np.array([Decimal(i) for i in range(2000)]) 
100 loops, best of 3: 7.39 ms per loop 
In [525]: timeit np.array([Decimal(i.item()) for i in np.arange(2000)]) 
100 loops, best of 3: 11.3 ms per loop 

Ich fragte mich, warum Sie str(i) verwendet. Aber dann habe ich festgestellt, dass Decimal nur ein paar der np.dtypes (nicht np.int32) nehmen kann. Meine Vermutung ist, das frompyfunc verwendet item() oder das Äquivalent Python Skalare zu produzieren:

In [523]: np.frompyfunc(Decimal,1,1)(np.arange(2)) 
Out[523]: array([Decimal('0'), Decimal('1')], dtype=object) 
In [524]: np.array([Decimal(i.item()) for i in np.arange(2)]) 
Out[524]: array([Decimal('0'), Decimal('1')], dtype=object) 

frompyfunc muss das Äquivalent von i.item() tun ein Python-Skalar vom np.int32 Objekt zu erzeugen.

+0

Ich brauche den np.array-Container, weil ich mathematische Operationen ausführe, die durch das numpige Modul –

+0

viel einfacher gemacht werden. Ja, ich habe einige Beispiele hinzugefügt, bei denen die Verwendung eines Objektarrays nützlich ist. Auf jeden Fall glaube ich nicht, dass Sie Geschwindigkeit oder Speicherverbrauch verbessern können. Sie werden Tausende von Dezimal-Objekten und 1000 von Zeigern zu diesen Objekten haben, unabhängig von der Container-Struktur. – hpaulj

+0

Ich habe eine Demonstration der Verwendung von 'frompyfunc' hinzugefügt, um die' Decimal'-Array-Erstellung zu erleichtern. – hpaulj

0

ich nicht numpy, aber die folgende können Sie einige Richtung Ihr Problem zu lösen:

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> import array 
>>> array_list = [ 
    array.array('q', [1, 2, 3, 4]), 
    array.array('q', [5, 6, 7, 8]), 
    array.array('q', [9, 10, 11, 12]) 
    ] 
>>> def iterate(iterable): 
    for index_a, value_a in enumerate(iterable): 
     try: 
      for index_b, value_b in iterate(value_a): 
       yield [index_a] + index_b, value_b 
     except TypeError: 
      yield [index_a], value_a 


>>> for index, value in iterate(array_list): 
    print(value, 'is at', index) 


1 is at [0, 0] 
2 is at [0, 1] 
3 is at [0, 2] 
4 is at [0, 3] 
5 is at [1, 0] 
6 is at [1, 1] 
7 is at [1, 2] 
8 is at [1, 3] 
9 is at [2, 0] 
10 is at [2, 1] 
11 is at [2, 2] 
12 is at [2, 3] 
>>> 

die Lösung für Ihr Problem zu vervollständigen, automatische Gießen oder Typumwandlung unterstützt werden:

>>> def iterate(iterable, cast): 
    for index_a, value_a in enumerate(iterable): 
     try: 
      for index_b, value_b in iterate(value_a, cast): 
       yield [index_a] + index_b, value_b 
     except TypeError: 
      yield [index_a], cast(value_a) 


>>> import decimal 
>>> for index, value in iterate(array_list, decimal.Decimal): 
    print(repr(value), 'came from', index) 


Decimal('1') came from [0, 0] 
Decimal('2') came from [0, 1] 
Decimal('3') came from [0, 2] 
Decimal('4') came from [0, 3] 
Decimal('5') came from [1, 0] 
Decimal('6') came from [1, 1] 
Decimal('7') came from [1, 2] 
Decimal('8') came from [1, 3] 
Decimal('9') came from [2, 0] 
Decimal('10') came from [2, 1] 
Decimal('11') came from [2, 2] 
Decimal('12') came from [2, 3] 
>>> 
+0

Ich werde definitiv in die Erstellung dieser iterierbaren Funktionen schauen müssen. Vielen Dank –

Verwandte Themen