2013-06-15 11 views
6

ich eine numpy.array von NxM zu NxMx3 zuordnen möchten, wo ein Vektor aus drei Elementen eine Funktion der ursprünglichen Eintrag:Mapping elementweise ein NumPy Array in ein Array von mehreren Dimensionen

lambda x: [f1(x), f2(x), f3(x)] 

jedoch Dinge wie numpy.vectorize nicht erlauben, Dimensionen zu ändern. Sicher, ich kann ein Array von Nullen erstellen und eine Schleife (and it is what I am doing by now), aber es klingt weder Pythonic noch effizient (wie jede Schleife in Python).

Gibt es eine bessere Möglichkeit, eine elementweise Operation für numpy.array auszuführen, die für jeden Eintrag einen Vektor erzeugt?

+0

Wenn 'N' und' M' signifikant größer als 3 sind, hat das Schleifen über die dritte Dimension einen unbedeutenden Effekt auf die Leistung. Und für For-Loops gibt es nichts Unpythonisches! Was nicht sehr numptonisch oder effizient ist, ist 'np.vectorize'. Sie könnten versuchen, 'f1',' f2' und 'f3' in eine einzige Funktion zu konvertieren, die Arrays und zurückgegebene Arrays verwendet. Ohne zu wissen, was Ihre Funktionen tun, ist es nicht möglich zu wissen, ob dieser Ansatz zu Ihrem Problem passt. – Jaime

+0

@Jaime Ich bin Schleife über N und M, nicht 3. Das Problem ist die Umwandlung komplexer Zahlen in drei Floats [R, G, B], so dass ich eine komplexe Funktion plotten kann (siehe den Link in der Frage). –

Antwort

3

Jetzt, wo ich den Code zu sehen, die für die meisten einfachen mathematischen Operationen können Sie lassen numpy den Looping zu tun, was als Vektorisierung bezeichnet wird oft:

def complex_array_to_rgb(X, theme='dark', rmax=None): 
    '''Takes an array of complex number and converts it to an array of [r, g, b], 
    where phase gives hue and saturaton/value are given by the absolute value. 
    Especially for use with imshow for complex plots.''' 
    absmax = rmax or np.abs(X).max() 
    Y = np.zeros(X.shape + (3,), dtype='float') 
    Y[..., 0] = np.angle(X)/(2 * pi) % 1 
    if theme == 'light': 
     Y[..., 1] = np.clip(np.abs(X)/absmax, 0, 1) 
     Y[..., 2] = 1 
    elif theme == 'dark': 
     Y[..., 1] = 1 
     Y[..., 2] = np.clip(np.abs(X)/absmax, 0, 1) 
    Y = matplotlib.colors.hsv_to_rgb(Y) 
    return Y 

Dieser Code sollte viel schneller als Ihres laufen.

+0

Ich wusste nicht, dass es möglich ist, Subarrays als 'Y [..., i]' oder 'Y [i, ...]' zu bezeichnen. Vielen Dank! Gibt es einen bestimmten Namen für diese Operation? (Ich googelte * Vektorisierung *, aber es gibt Dinge wie 'np.vectorize' zurück.) –

+1

Es ist die _ellipsis_ Schreibweise. Korrigiert den Tippfehler. – Jaime

+0

Ich sehe. Jetzt sehe ich ein paar Anmerkungen dazu: http://Stackoverflow.com/a/773472/907575 und http://StackOverflow.com/Questions/118370/How-Do-You-use-the-ellips-is-Slicing-Syntax- In-Python. –

4

Wenn ich Ihr Problem richtig verstehe, ich schlage vor, Sie verwenden np.dstack:

Docstring: 
Stack arrays in sequence depth wise (along third axis). 

Takes a sequence of arrays and stack them along the third axis 
to make a single array. Rebuilds arrays divided by `dsplit`. 
This is a simple way to stack 2D arrays (images) into a single 
3D array for processing. 

In [1]: a = np.arange(9).reshape(3, 3) 

    In [2]: a 
    Out[2]: 
    array([[0, 1, 2], 
      [3, 4, 5], 
      [6, 7, 8]]) 

    In [3]: x, y, z = a*1, a*2, a*3 # in your case f1(a), f2(a), f3(a) 

    In [4]: np.dstack((x, y, z)) 
    Out[4]: 
    array([[[ 0, 0, 0], 
      [ 1, 2, 3], 
      [ 2, 4, 6]], 

      [[ 3, 6, 9], 
      [ 4, 8, 12], 
      [ 5, 10, 15]], 

      [[ 6, 12, 18], 
      [ 7, 14, 21], 
      [ 8, 16, 24]]]) 
+0

Ich würde vermeiden, 'x, y, z' vor dem Speichern von Speicher zu definieren, die Funktionen innerhalb 'np.dstack() aufrufen' –

+0

@sgpc - Sie haben Recht. Ich habe es nur aus Gründen der Klarheit getan. – root

+0

+1 Schön und funktioniert. Ich akzeptierte Jaimes Antwort, da sie für meinen Zweck und für einige Verallgemeinerungen bequemer ist. –