Puisque vous êtes à la recherche en arrière sur les valeurs précédentes pour voir s'il y a des valeurs consécutives, vous allez devoir interagir avec des indices en quelque sorte. Cette solution examine d'abord les valeurs antérieures à la valeur de l'index en cours pour voir si elles sont inférieures ou supérieures à la valeur, puis définit les valeurs sur False s'il y avait un False qui la suit. Cela évite également de créer des itérateurs sur le DataFrame, ce qui peut accélérer les opérations pour des ensembles de données plus volumineux.
import pandas as pd
from operator import gt, lt
a = pd.Series([30, 10, 20, 25, 35, 15])
def consecutive_run(op, ser, i):
"""
Sum the uninterrupted consecutive runs at index i in the series where the previous data
was true according to the operator.
"""
thresh_all = op(ser[:i], ser[i])
# find any data where the operator was not passing. set the previous data to all falses
non_passing = thresh_all[~thresh_all]
start_idx = 0
if not non_passing.empty:
# if there was a failure, there was a break in the consecutive truth values,
# so get the final False position. Starting index will be False, but it
# will either be at the end of the series selection and will sum to zero
# or will be followed by all successive True values afterwards
start_idx = non_passing.index[-1]
# count the consecutive runs by summing from the start index onwards
return thresh_all[start_idx:].sum()
res = pd.concat([a, a.index.to_series().map(lambda i: consecutive_run(gt, a, i)),
a.index.to_series().map(lambda i: consecutive_run(lt, a, i))],
axis=1)
res.columns = ['Value', 'Higher than streak', 'Lower than streak']
print(res)
Résultat:
Value Higher than streak Lower than streak
0 30 0 0
1 10 1 0
2 20 0 1
3 25 0 2
4 35 0 4
5 15 3 0
Merci, je ne pensais pas que nous trouverions une solution qui évite les boucles. –
Mise à jour pour utiliser un algorithme de sommation légèrement plus efficace en ne saisissant que les valeurs successives, puis en additionnant. – benjwadams