2015-05-15 6 views
10

Cython'u göreceli olarak basit olan bir Pandas DataFrame hesaplamasını hızlandırmak için kullanıyorum: DataFrame'deki her satırın üzerinde yineleme yapmak, bu satırı kendisine ve DataFrame'deki kalan tüm satırlara eklemek, Bunları her bir satırda toplayın ve bu miktarların listesini verin. DataFrame'deki satırlar tükendiğinden, bu dizilerin uzunluğu azalacaktır. Bu seriler, dizin satır numarasına yazılan bir sözlük olarak saklanır.Cython'u Pandalar'a uygulama 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 

Kenara bu işlevin üstünde %%cython eklemesini, herkes ben dublelere DataFrame değerlerini dönüştürmek ve daha sonra bu kodu cythonize için cdefs kullanma hakkında gitmek istiyorum nasıl bir öneri var mı?

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

ve beklenen çıkışı: Aşağıda

bazı kukla veridir sadece daha hızlı yapmaya çalışıyor ve özellikle Cython kullanmıyorsanız

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

Duygularım, çok miktarda kazanamayacağınızdır - işin çoğu (vectorized, float + array) ilavesi veya toplamıdır. Her ikisi de Cython'da olduğu gibi kalır. Döngünün dışında bir kere toplamı (eksen = 1) 'yaparak bir (Cython tabanlı olmayan) hızlandırma elde edebilirsiniz. – DavidW

+0

Cython'da dataframes/series ile doğrudan çalışamazsınız, ancak alttaki numpy dizisiyle çalışmanız gerekir. Bir eğitim için buraya bakın: http://pandas.pydata.org/pandas-docs/stable/enhancingperf.html – joris

cevap

13

, bunu sadece ediyorum düz numpy (yaklaşık 50x daha hızlı).

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 

Genellikle pandalar size Numpy göre kolaylıklar bir sürü verir, konuşma, ama havai maliyetler vardır. Bu yüzden, pandaların hiçbir şey eklemediği durumlarda, genellikle uyuşturarak şeyleri hızlandırabilirsiniz. Başka bir örnek için, kabaca benzer bir hız farkı (yaklaşık 23x) gösteren bu question'a bakın.