Вот способ сделать это, в основном используя shift
:
df["start_of_range"] = (df.Value >= 40) & (df.Value.shift() < 40)
df["end_of_range"] = (df.Value >= 40) & (df.Value.shift(-1) < 40)
t = df[df["start_of_range"] | df["end_of_range"] ]
# t is now all the rows which are either at the beginning or at the
# end of a range. We now want to 'fold it' into two - odd rows
# are start of ranges, and even rows are end of ranges.
t.index=range(len(t))
starts = t[t.index % 2 == 0][["Timestamp", "Value"]]
ends = t[t.index % 2 == 1][["Timestamp", "Value"]]
t = pd.concat([starts.reset_index(), ends.reset_index()], axis=1)
t = t.drop("index", axis=1)
t.columns = ["start_window", "Value", "end_window", "Value"]
print(t)
Результат:
start_window Value end_window Value
0 2012-06-24 07:51:54.613 40.5 2012-06-24 08:05:34.997 40.0
1 2012-06-24 08:22:59.447 41.0 NaT NaN