Try:
# remove the `nan` values
s = df.stack().reset_index(name='value')
# enumerate date from bottom up
count_from_bottom = s[::-1].groupby('level_1').cumcount()[::-1]
# compare the enumeration with the respective threshold and extract data
endval = s.loc[count_from_bottom < s['level_1'].map(df_periods.iloc[0])]
Output:
level_0 level_1 value
4 0 col5 1.0
9 1 col5 1.0
11 2 col2 9.0
14 2 col5 1.0
16 3 col2 9.0
17 3 col3 6.0
19 3 col5 1.0
20 4 col1 8.0
21 4 col2 9.0
22 4 col3 6.0
23 4 col4 7.0
24 5 col1 8.0
25 5 col3 6.0
26 5 col4 7.0
27 6 col1 8.0
28 6 col3 6.0
29 6 col4 7.0
30 7 col1 8.0
31 7 col3 6.0
32 7 col4 7.0
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…