Если ваши данные могут содержать «прогоны» последовательных значений выше, ниже или между пороговыми значениями, и вы хотите подсчитывать прогоны вместо отдельных точек данных, вы можете пометить свои данные, свернуть последовательные метки, отфильтровать и подсчитать:
In [64]: df = pd.DataFrame({'Temp': [50, 47.7, 45, 0, 0, -1, -1, -2, -10, -30,
...: -45, -45, -46, -20, -1, 2, 2, 10, 10, 20,
...: 35.5, 35, 36, 20, 0, -10, -45.1, -50]})
Создайте метки:
In [65]: df['Category'] = 0
In [66]: df.loc[df['Temp'] <= -45, 'Category'] = -1
In [67]: df.loc[df['Temp'] >= 35, 'Category'] = 1
In [68]: df
Out[68]:
Temp Category
0 50.0 1
1 47.7 1
2 45.0 1
3 0.0 0
...
9 -30.0 0
10 -45.0 -1
11 -45.0 -1
12 -46.0 -1
13 -20.0 0
...
19 20.0 0
20 35.5 1
21 35.0 1
22 36.0 1
23 20.0 0
24 0.0 0
25 -10.0 0
26 -45.1 -1
27 -50.0 -1
Затем используйте Series.shift()
до для сравнения и свертывания последовательных значений :
In [69]: df[df['Category'].shift() != df['Category']]
Out[69]:
Temp Category
0 50.0 1
3 0.0 0
10 -45.0 -1
13 -20.0 0
20 35.5 1
23 20.0 0
26 -45.1 -1
Отсюда легко фильтровать и рассчитывать по категориям:
In [70]: collapsed = df[df['Category'].shift() != df['Category']]
In [71]: (collapsed['Category'] != 0).sum()
Out[71]: 4
In [72]: (collapsed['Category'] == 0).sum()
Out[72]: 3
Series.value_counts()
также могут быть полезны:
In [73]: collapsed['Category'].value_counts()
Out[73]:
0 3
-1 2
1 2
Name: Category, dtype: int64
Как написать функцию, которая ... время, когда данные находились в диапазоне?
Если у вас есть данные временного ряда, легко перенести свернутые данные еще разчтобы рассчитать продолжительность прогонов (показано здесь с использованием целочисленного индекса):
In [74]: fake_time_series = collapsed.reset_index()
In [75]: fake_time_series
Out[75]:
index Temp Category
0 0 50.0 1
1 3 0.0 0
2 10 -45.0 -1
3 13 -20.0 0
4 20 35.5 1
5 23 20.0 0
6 26 -45.1 -1
In [76]: fake_time_series.shift(-1)['index'] - fake_time_series['index']
Out[76]:
0 3.0
1 7.0
2 3.0
3 7.0
4 3.0
5 3.0
6 NaN
Name: index, dtype: float64