2013-05-20 18 views
7

Betrachten eine Spezifikation numpy Arrays, die typisch für die Angabe matplotlib Daten Plotten:Iterieren zwei Arrays, ohne nditer, in numpy?

t = np.arange(0.0,1.5,0.25) 
s = np.sin(2*np.pi*t) 

Grundsätzlich Diese speichert die Koordinaten x unserer (x,y) Datenpunkte in dem Array t; und die resultierenden Koordinaten y (Ergebnis von y = f (x), in diesem Fall sin(x)) in dem Array s. Dann ist es sehr bequem, die numpy.nditer Funktion zu verwenden aufeinanderfolgende Paare von Einträgen in t und s zu erhalten, was die (x,y) einen Datenpunkt koordinieren, wie in:

for x, y in np.nditer([t,s]): 
    print("xy: %f:%f" % (x,y)) 

Also, ich bin das folgende Snippet versuchen als test.py:

import numpy as np 
print("numpy version {0}".format(np.__version__)) 
t = np.arange(0.0,1.5,0.25) ; print("t", ["%+.2e"%i for i in t]) 
s = np.sin(2*np.pi*t)   ; print("s", ["%+.2e"%i for i in s]) 
print("i", ["% 9d"%i for i in range(0, len(t))]) 
for x, y in np.nditer([t,s]): 
    print("xy: %f:%f" % (x,y)) 

... und die Ergebnisse sind:

$ python3.2 test.py 
numpy version 1.7.0 
t ['+0.00e+00', '+2.50e-01', '+5.00e-01', '+7.50e-01', '+1.00e+00', '+1.25e+00'] 
s ['+0.00e+00', '+1.00e+00', '+1.22e-16', '-1.00e+00', '-2.45e-16', '+1.00e+00'] 
i ['  0', '  1', '  2', '  3', '  4', '  5'] 
xy: 0.000000:0.000000 
xy: 0.250000:1.000000 
xy: 0.500000:0.000000 
xy: 0.750000:-1.000000 
xy: 1.000000:-0.000000 
xy: 1.250000:1.000000 

$ python2.7 test.py 
numpy version 1.5.1 
('t', ['+0.00e+00', '+2.50e-01', '+5.00e-01', '+7.50e-01', '+1.00e+00', '+1.25e+00']) 
('s', ['+0.00e+00', '+1.00e+00', '+1.22e-16', '-1.00e+00', '-2.45e-16', '+1.00e+00']) 
('i', ['  0', '  1', '  2', '  3', '  4', '  5']) 
Traceback (most recent call last): 
    File "test.py", line 10, in <module> 
    for x, y in np.nditer([t,s]): 
AttributeError: 'module' object has no attribute 'nditer' 

Ah - Es stellt sich heraus, dass the iterator object nditer, introduced in NumPy 1.6, ist nicht verfügbar in der numpy Version meiner Python 2.7 Installation.

Also, wie ich diese spezielle Version auch unterstützen möchte, müsste ich einen Weg finden, für ältere numpy arbeiten - aber ich möchte immer noch den Komfort einfach for x,y in somearray angeben, und erhalten Sie die Koordinaten direkt in die Schleife.

Nach einiger Flickschusterei mit numpy Dokumentation, ich kam mit dieser getXyIter Funktion auf:

import numpy as np 
print("numpy version {0}".format(np.__version__)) 
t = np.arange(0.0,1.5,0.25) ; print("t", ["%+.2e"%i for i in t]) 
s = np.sin(2*np.pi*t)   ; print("s", ["%+.2e"%i for i in s]) 
print("i", ["% 9d"%i for i in range(0, len(t))]) 

def getXyIter(inarr): 
    if np.__version__ >= "1.6.0": 
    return np.nditer(inarr.tolist()) 
    else: 
    dimensions = inarr.shape 
    xlen = dimensions[1] 
    xinds = np.arange(0, xlen, 1) 
    return np.transpose(np.take(inarr, xinds, axis=1)) 

for x, y in getXyIter(np.array([t,s])): 
    print("xyIt: %f:%f" % (x,y)) 

for x, y in np.nditer([t,s]): 
    print("xynd: %f:%f" % (x,y)) 

... die

gut zu funktionieren scheint
$ python2.7 test.py 
numpy version 1.5.1 
('t', ['+0.00e+00', '+2.50e-01', '+5.00e-01', '+7.50e-01', '+1.00e+00', '+1.25e+00']) 
('s', ['+0.00e+00', '+1.00e+00', '+1.22e-16', '-1.00e+00', '-2.45e-16', '+1.00e+00']) 
('i', ['  0', '  1', '  2', '  3', '  4', '  5']) 
xyIt: 0.000000:0.000000 
xyIt: 0.250000:1.000000 
xyIt: 0.500000:0.000000 
xyIt: 0.750000:-1.000000 
xyIt: 1.000000:-0.000000 
xyIt: 1.250000:1.000000 
Traceback (most recent call last): 
    File "test.py", line 23, in <module> 
    for x, y in np.nditer([t,s]): 
AttributeError: 'module' object has no attribute 'nditer' 
$ python3.2 test.py 
numpy version 1.7.0 
t ['+0.00e+00', '+2.50e-01', '+5.00e-01', '+7.50e-01', '+1.00e+00', '+1.25e+00'] 
s ['+0.00e+00', '+1.00e+00', '+1.22e-16', '-1.00e+00', '-2.45e-16', '+1.00e+00'] 
i ['  0', '  1', '  2', '  3', '  4', '  5'] 
xyIt: 0.000000:0.000000 
xyIt: 0.250000:1.000000 
xyIt: 0.500000:0.000000 
xyIt: 0.750000:-1.000000 
xyIt: 1.000000:-0.000000 
xyIt: 1.250000:1.000000 
xynd: 0.000000:0.000000 
xynd: 0.250000:1.000000 
xynd: 0.500000:0.000000 
xynd: 0.750000:-1.000000 
xynd: 1.000000:-0.000000 
xynd: 1.250000:1.000000 

Meine Frage ist - das ist der Weg , diese Art von Iteration soll in Versionen von 0.1.6.0 durchgeführt werden?

Antwort

3

Wie wäre es concatenating den beiden Vektoren in ein Array:

for x,y in np.c_[t,s]: 
    print("xy: %f:%f" % (x,y)) 

Dies gibt

xy: 0.000000:0.000000 
xy: 0.250000:1.000000 
xy: 0.500000:0.000000 
xy: 0.750000:-1.000000 
xy: 1.000000:-0.000000 
xy: 1.250000:1.000000 

Wenn Sie iterieren wollen, so können Sie Speicherplatz sparen, können Sie die itertools.izip Funktion:

for x,y in itertools.izip(t,s): 
    print("xy: %f:%f" % (x,y)) 
0

for x, y in zip(t,s):. Für 1D-Arrays ist es wirklich so einfach.

Verifiziert, um in Python 2 und Python 3 zu arbeiten. Zip() gibt eine Liste auf Python2 zurück, so wie DiggyF vorschlägt, itertools.izip() könnte für große Arrays besser geeignet sein.

Bei> 1D-Arrays bewegt sich die Iteration durch die letzte Dimension, wobei (N-1) D-Arrays zurückgegeben werden. Wenn Sie mit N-d-Arrays arbeiten müssen, ist dies möglicherweise nicht das, was Sie wollen.

Egal, es ist zweifellos portabel, und Iteration auf Array-Objekte soll diese Art von Usecase unterstützen :)