2013-05-20 12 views
7

Rozważmy specyfikację numpy tablic, typowe dla określenia matplotlib wykreślania danych:Iterowanie dwóch tablic, bez nditera, w numpy?

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

Zasadniczo, przechowuje współrzędne x naszych (x,y) punktów danych w tablicy t; i uzyskane współrzędne y (wynik y = f (x), w tym przypadku sin(x)) w macierzy s. Następnie, to jest bardzo wygodny w użyciu funkcji numpy.nditer celu uzyskania kolejnych par wpisów w t i s, reprezentujący (x,y) współrzędna punktu danych, na przykład:

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

So, próbuję następujący fragment jak 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)) 

... a wyniki są następujące:

$ 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 - okazuje się, że the iterator object nditer, introduced in NumPy 1.6, nie jest dostępny w wersji numpy mojej instalacji Pythona 2.7.

Tak, jak chciałbym wesprzeć tę konkretną wersję też, że muszę znaleźć sposób pracy dla starszych numpy - ale ja nadal jak wygody po prostu określając for x,y in somearray, a uzyskanie współrzędnych bezpośrednio w pętla.

Po pewnym ingerować numpy dokumentacji, wymyśliłem tego getXyIter funkcję:

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)) 

... co wydaje się działać prawidłowo

$ 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 

Moje pytanie brzmi - czy to jest droga , ten rodzaj iteracji powinien zostać wykonany w wersjach numpy < 1.6.0?

Odpowiedz

3

Jak o concatenating dwóch wektorów do tablicy:

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

Daje to

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 

Jeśli chcesz iteracji, dzięki czemu można zaoszczędzić pamięć, można użyć funkcji itertools.izip:

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

for x, y in zip(t,s):. W przypadku macierzy 1d jest to naprawdę proste.

Zweryfikowany do pracy zarówno w Pythonie 2, jak i Pythonie 3. zip() zwraca listę na Python2 jednak, jak sugeruje DiggyF, może być bardziej odpowiedni dla dużych tablic.

Dla tablic 1D iteracja przechodzi przez tablice D z ostatnimi wymiarami (N-1). Jeśli masz do czynienia z tablicami N-D, może to być lub nie być to, czego chcesz.

Bez względu na to, jest niewątpliwie przenośny, a iteracja na obiektach tablicowych ma na celu wsparcie tego rodzaju zastosowań :)