That is the difference between the long- and short-form of a table.
You can use .stack(), .reset_index(), and .rename() to convert your desired format.
df.stack(0).reset_index(1).rename(columns={'level_1': 'type'})
Here's an awesome article with nice visualizations describing how stack and unstack works.
And here's the result step by step:
>>> df
price cost
mean max min mean max min
0 1 1 1 1 2 3
1 2 2 2 1 2 3
2 3 3 3 1 2 3
>>> df.stack(level=0)
max mean min
0 cost 2 1 3
price 1 1 1
1 cost 2 1 3
price 2 2 2
2 cost 2 1 3
price 3 3 3
>>> df.stack(level=0).reset_index(level=1)
level_1 max mean min
0 cost 2 1 3
0 price 1 1 1
1 cost 2 1 3
1 price 2 2 2
2 cost 2 1 3
2 price 3 3 3
>>> df.stack(level=0).reset_index(level=1).rename(columns={'level_1': 'type'})
type max mean min
0 cost 2 1 3
0 price 1 1 1
1 cost 2 1 3
1 price 2 2 2
2 cost 2 1 3
2 price 3 3 3
If you need to maintain the id column (it is not a useless auto-incrementing column), you can add an extra set_index and reset_index to keep that column:
>>> df.set_index('id').stack(0).reset_index(1) \
.rename(columns={'level_1': 'type'}).reset_index()
id type max mean min
0 0 cost 2 1 3
1 0 price 1 1 1
2 1 cost 2 1 3
3 1 price 2 2 2
4 2 cost 2 1 3
5 2 price 3 3 3