В случае простого информационного кадра это должно работать:
import pandas as pd
df = pd.DataFrame({
'a': ['a1', 'a1', 'a2', 'a2',],
'b': ['b1', 'b2', 'b2', 'b2',],
'2018 jan': [0, 4, 8, 12],
'2018 feb': [1, 5, 9, 13],
'2019 jan': [2, 6, 10, 14],
'2019 feb': [3, 7, 11, 15],
})
df = df.melt(id_vars=['a', 'b'], var_name='date', value_name='value')
df['date'] = df['date'].str.split(' ')
df['year'] = df['date'].str[0]
df['month'] = df['date'].str[1]
df.drop(columns='date', inplace=True)
Вывод:
a b value year month
0 a1 b1 0 2018 jan
1 a1 b2 4 2018 jan
2 a2 b2 8 2018 jan
3 a2 b2 12 2018 jan
4 a1 b1 1 2018 feb
5 a1 b2 5 2018 feb
6 a2 b2 9 2018 feb
7 a2 b2 13 2018 feb
8 a1 b1 2 2019 jan
9 a1 b2 6 2019 jan
10 a2 b2 10 2019 jan
11 a2 b2 14 2019 jan
12 a1 b1 3 2019 feb
13 a1 b2 7 2019 feb
14 a2 b2 11 2019 feb
15 a2 b2 15 2019 feb
Если у вас есть несколько многоиндексных столбцов, как указано в комментарии, здесь вы можетепреобразовать его в простой формат данных:
df = pd.read_csv('file.csv', header=[0,1])
df.columns = [' '.join(col).strip() for col in df.columns.values]
df.rename(columns={'a Unnamed: 0_level_1': 'a', 'b Unnamed: 1_level_1': 'b'}, inplace=True)