Первое, что вам нужно сделать, это создать справочный столбец. Очень наивный способ похож на
df.loc[:,'Zone_shift']=df.loc[:,'Zone'].shift(1)
df.loc[:,'Timeframe_shift']=df.loc[:,'Timeframe'].shift(1)
df.loc[:,'Groupby'] = df.apply(lambda x: 0 if x['Zone']==x['Zone_shift'] and x['Timeframe']==x['Timeframe_shift'] else 1, axis=1)
df.loc[:,'Groupby'] = df.loc[:,'Groupby'].cumsum()
После добавления справочных данных, фрейм данных выглядит как
Zone Timeframe dV Zone_shift Timeframe_shift Groupby
0 ZoneA Beforestimulation 15.625 nan nan 1
1 ZoneA Beforestimulation 42.241 ZoneA Beforestimulation 1
2 ZoneA Beforestimulation 59.498 ZoneA Beforestimulation 1
3 ZoneB Beforestimulation 39.062 ZoneA Beforestimulation 2
4 ZoneB Beforestimulation 59.333 ZoneB Beforestimulation 2
5 ZoneA Beforestimulation 46.153 ZoneB Beforestimulation 3
6 ZoneA Beforestimulation 22.271 ZoneA Beforestimulation 3
7 ZoneC Afterstimulation 6.9444 ZoneA Beforestimulation 4
8 ZoneC Afterstimulation 7.8125 ZoneC Afterstimulation 4
9 ZoneA Afterstimulation 17.469 ZoneC Afterstimulation 5
10 ZoneA Afterstimulation 6.9444 ZoneA Afterstimulation 5
11 ZoneA Afterstimulation 24.705 ZoneA Afterstimulation 5
Тогда вам нужно сгруппировать только по
df.groupby(['Groupby','Zone','Timeframe']).mean()
И конечный результат будет выглядеть как
Groupby Zone Timeframe dV
1 ZoneA Beforestimulation 39.12154433333333
2 ZoneB Beforestimulation 49.1979295
3 ZoneA Beforestimulation 34.212463
4 ZoneC Afterstimulation 7.378472
5 ZoneA Afterstimulation 16.373006333333333