2015-05-15 9 views
10

Ich versuche Cython zu verwenden, um eine Pandas Datenrahmen der Berechnung zu beschleunigen, die relativ einfach: in dem Datenrahmen über jede Zeile laufen, fügen Sie diese Zeile auf mich selbst und zu den restlichen Zeilen in dem Datenrahmen, summiere diese über jede Reihe und erhalte die Liste dieser Summen. Die Länge dieser Reihen verringert sich, wenn die Zeilen im DataFrame erschöpft sind. Diese Reihen werden als ein Verzeichnis gespeichert, das auf der Indexreihennummer eingegeben wird.Wie bewerbe ich Cython zu Pandas Dataframe

def foo(df): 
    vals = {i: (df.iloc[i, :] + df.iloc[i:, :]).sum(axis=1).values.tolist() 
      for i in range(df.shape[0])} 
    return vals 

Neben %%cython an der Spitze dieser Funktion hinzufügt, hat jemand eine Empfehlung, wie ich gehen würde cdefs über die Verwendung der Datenrahmen Werte verdoppelt zu konvertieren und dann diesen Code cythonize?

Im Folgenden einige Dummy-Daten:

>>> df 

      A   B   C   D   E 
0 -0.326403 1.173797 1.667856 -1.087655 0.427145 
1 -0.797344 0.004362 1.499460 0.427453 -0.184672 
2 -1.764609 1.949906 -0.968558 0.407954 0.533869 
3 0.944205 0.158495 -1.049090 -0.897253 1.236081 
4 -2.086274 0.112697 0.934638 -1.337545 0.248608 
5 -0.356551 -1.275442 0.701503 1.073797 -0.008074 
6 -1.300254 1.474991 0.206862 -0.859361 0.115754 
7 -1.078605 0.157739 0.810672 0.468333 -0.851664 
8 0.900971 0.021618 0.173563 -0.562580 -2.087487 
9 2.155471 -0.605067 0.091478 0.242371 0.290887 

und erwartete Ausgabe:

>>> foo(df) 

{0: [3.7094795101205236, 
    2.8039983729106, 
    2.013301815968468, 
    2.24717712931852, 
    -0.27313665495940964, 
    1.9899718844711711, 
    1.4927321304935717, 
    1.3612155622947018, 
    0.3008239883773878, 
    4.029880107986906], 

. . . 

6: [-0.72401524913338, 
    -0.8555318173322499, 
    -1.9159233912495635, 
    1.813132728359954], 
7: [-0.9870483855311194, -2.047439959448434, 1.6816161601610844], 
8: [-3.107831533365748, 0.6212245862437702], 
9: [4.350280705853288]} 
+1

Mein Gefühl ist, dass Sie nicht eine riesige Menge gewinnen - die meiste Arbeit ist entweder in dem (vektorisiert, + Array float) hinaus oder in der Summe. Beide würden so bleiben wie in Cython. Sie könnten ein (nicht-Cython basierte) Speed-up erhalten, indem Sie die 'Summe tun (Achse = 1)' einmal außerhalb der Schleife. – DavidW

+0

Sie können nicht direkt mit Datenrahmen/Serie in cython arbeiten, aber Sie werden mit dem zugrunde liegenden numpy Array arbeiten. Sehen Sie hier für ein Tutorial: http://pandas.pydata.org/pandas-docs/stable/enhancingperf.html – joris

Antwort

13

Wenn Sie nur versuchen, es schneller zu tun und nicht speziell cython verwenden, würde ich es einfach tun in einfacher Anzahl (ca. 50x schneller).

def numpy_foo(arr): 
    vals = {i: (arr[i, :] + arr[i:, :]).sum(axis=1).tolist() 
      for i in range(arr.shape[0])} 
    return vals 

%timeit foo(df) 
100 loops, best of 3: 7.2 ms per loop 

%timeit numpy_foo(df.values) 
10000 loops, best of 3: 144 µs per loop 

foo(df) == numpy_foo(df.values) 
Out[586]: True 

Generell Pandas Sie numpy eine Menge Annehmlichkeiten relativ gibt, aber es gibt Gemeinkosten. In Situationen, in denen Pandas nicht wirklich etwas hinzufügt, können Sie die Dinge in der Regel beschleunigen, indem Sie es in Anführungszeichen tun. Für ein weiteres Beispiel finden Sie in diesen question ich gefragt, die eine in etwa vergleichbare Geschwindigkeitsdifferenz zeigte (etwa 23x).