2016-09-12 2 views
0

Ich gewöhne mich an die Ängstlichkeit von numpy.apply_along_axis und ich fragte mich, ob ich die Vektorisierung auf die nächste Ebene bringen könnte - hauptsächlich für Geschwindigkeitszwecke, die das Potenzial der Funktion nutzt versuchen, die for-Schleife zu beseitigen, die ich in dem Code unten habe.Optimierung & numpy Vektorisierung: wiederhole Satz von Arrays

from pandas import DataFrame 
import numpy as np 
from time import time 

list_away = [] 

new_data_morphed = DataFrame(np.random.rand(1000, 5)).transpose().as_matrix() 
group_by_strat_full = DataFrame([ 
    [0, 1, 4], 
    [1, 2, 3], 
    [2, 3, 4], 
    [0, 1, 4]], columns=['add_mask_1', 'add_mask_2', 'add_mask_3', ]) 

all_the_core_strats = [lambda x: x.prod(), lambda x: sum(x), ] 

def run_strat_mod(df_vals, core_strat, dict_mask_1, dict_mask_2, dict_mask_3, list_away): 
    slice_df = df_vals[[dict_mask_1, dict_mask_2, dict_mask_3]] 
    # TODO: this comprehension list should be vectorized 
    to_append = [np.apply_along_axis(lambda x: u(x), 0, slice_df) for u in core_strat] 
    list_away.append(to_append) 

t1 = time() 
results_3 = group_by_strat_full.apply(lambda x: run_strat_mod(
    new_data_morphed, 
    all_the_core_strats, 
    x['add_mask_1'], 
    x['add_mask_2'], 
    x['add_mask_3'], 
    list_away), axis=1) 

t2 = time() 
print(abs(t1 - t2)) 

, um das zu tun, dachte ich an den anfänglichen Satz von Arrays wiederholt wird, ist, dass slice_df so dass ich numpy.apply_along_axis auf einen neuen all_the_core_strats_mod anwenden könnte.

mit Ausgang, von hier:

print(slice_df) 
    [[[ 0.91302268 0.6172959 0.05478723 ..., 0.37028638 0.52116891 
    0.14158221] 
    [ 0.72579223 0.78732047 0.61335979 ..., 0.46359203 0.27593171 
    0.73700975] 
    [ 0.21706977 0.87639447 0.44936619 ..., 0.44319643 0.53712003 
    0.8071096 ]] 

dazu:

slice_df = np.array([df_vals[[dict_mask_1, dict_mask_2, dict_mask_3]]] * len(core_strat)) 
print(slice_df) 

[[[ 0.91302268 0.6172959 0.05478723 ..., 0.37028638 0.52116891 
    0.14158221] 
    [ 0.72579223 0.78732047 0.61335979 ..., 0.46359203 0.27593171 
    0.73700975] 
    [ 0.21706977 0.87639447 0.44936619 ..., 0.44319643 0.53712003 
    0.8071096 ]] 

[[ 0.91302268 0.6172959 0.05478723 ..., 0.37028638 0.52116891 
    0.14158221] 
    [ 0.72579223 0.78732047 0.61335979 ..., 0.46359203 0.27593171 
    0.73700975] 
    [ 0.21706977 0.87639447 0.44936619 ..., 0.44319643 0.53712003 
    0.8071096 ]]] 

und dann

def all_the_core_strats_mod(x): 
    return [x[0].prod(), sum(x[1])] 

to_append = np.apply_along_axis(all_the_core_strats_mod, 0, slice_df) 

aber es funktioniert nicht, wie ich es mir vorgestellt (Funktionen separat zu jedem dupliziert Anwendung Block).

alle Ideen sind willkommen

Antwort

0
def foo(x): 
    print(x) # add for diagnosis 
    return [x[0].prod(), x[1].sum()] 

Sie es auf einem 3D-Array, das der Einfachheit halber verwende ich werde (je schneller, desto besser!):

In [64]: x=np.arange(2*3*2).reshape(2,3,2) 

In [66]: np.apply_along_axis(foo,0,x) 
[0 6] 
[1 7] 
[2 8] 
[3 9] 
[ 4 10] 
[ 5 11] 
Out[66]: 
array([[[ 0, 1], 
     [ 2, 3], 
     [ 4, 5]], 

     [[ 6, 7], 
     [ 8, 9], 
     [10, 11]]]) 

So apply_along_axis ist vorbei an foo, x[:,0,0], x[:,0,1], x[:,1,0], usw. Unter prod und sum auf diese 2 Zahlen ist nicht sehr aufregend.

apply_along_axis ist nur eine bequeme Art und Weise zu tun:

for i in range(x.shape[1]): 
    for j in range(x.shape[2]): 
     ret[:,i,j] = foo(x[:,i,j])