2017-03-18 3 views
1

Dans mon cadre de données, je veux créer une colonne '5D_Peak' comme un max roulement, puis une autre colonne avec le nombre de roulement de données historiques qui est proche du pic. Je me demande s'il existe un moyen plus simple de vectoriser simplement ou idéalement le calcul.Pandas: roulement nombre si dans une boucle

C'est mes codes d'une manière simple mais compliquée:

import numpy as np 
import pandas as pd 

df = pd.DataFrame([[1,2,4],[4,5,2],[3,5,8],[1,8,6],[5,2,8],[1,4,10],[3,5,9],[1,4,7],[1,4,6]], columns=list('ABC')) 

df['5D_Peak']=df['C'].rolling(window=5,center=False).max() 

for i in range(5,len(df.A)): 
    val=0 
    for j in range(i-5,i): 
     if df.loc[j,'C']>df.loc[i,'5D_Peak']-2 and df.loc[j,'C']<df.loc[i,'5D_Peak']+2: 
      val+=1 
    df.loc[i,'5D_Close_to_Peak_Count']=val 

C'est la sortie que je veux:

A B C 5D_Peak 5D_Close_to_Peak_Count 
0 1 2 4  NaN      NaN 
1 4 5 2  NaN      NaN 
2 3 5 8  NaN      NaN 
3 1 8 6  NaN      NaN 
4 5 2 8  8.0      NaN 
5 1 4 10  10.0      0.0 
6 3 5 9  10.0      1.0 
7 1 4 7  10.0      2.0 
8 1 4 6  10.0      2.0 

Répondre

1

Je crois que c'est ce que vous voulez. Vous pouvez définir les deux valeurs ci-dessous:

'''the window within which to search "close-to_peak" values''' 
lkp_rng = 5 

'''how close is close?''' 
closeness_measure = 2 

'''function to count the number of "close-to_peak" values in the lkp_rng''' 
fc = lambda x: np.count_nonzero(np.where(x >= x.max()- closeness_measure)) 

'''apply fc to the coulmn you choose''' 
df['5D_Close_to_Peak_Count'] = df['C'].rolling(window=lkp_range,center=False).apply(fc) 
df.head(10) 
     A B C 5D_Peak  5D_Close_to_Peak_Count 
    0 1 2 4 NaN   NaN 
    1 4 5 2 NaN   NaN 
    2 3 5 8 NaN   NaN 
    3 1 8 6 NaN   NaN 
    4 5 2 8 8.0   3.0 
    5 1 4 10 10.0   3.0 
    6 3 5 9 10.0   3.0 
    7 1 4 7 10.0   3.0 
    8 1 4 6 10.0   2.0 

Je devine ce que vous entendez par "données historiques".

+0

Merci. Cela résout mon problème aussi. Mais je suppose que la méthode de vectorisation proposée par JohnE est plus rapide? – thunderlion

+0

Si vous utilisez un ordinateur portable ipython, insérez simplement '%% prun' en haut de la cellule dans laquelle vous exécutez le code. Il donnera une longue liste, avec un résumé d'une phrase en haut. J'obtiens '" 826 appels de fonction (820 appels primitifs) en 0.003 secondes "' pour le mien. Si vous insérez '%% timeit' à la place et exécutez la cellule, cela donne' "1000 boucles, le meilleur de 3: 745 μs par boucle". Vous pouvez également vérifier l'autre code. » – user2738815

+0

@JohnE N'avez-vous pas testé la vitesse de votre code? – user2738815