Usando el nombre de la columna como un nuevo atributo en pandas

Tengo la siguiente estructura de datos

Date Agric Food 01/01/1990 1.3 0.9 01/02/1990 1.2 0.9 

Me gustaría convertirlo en el formato.

 Date Sector Beta 01/01/1990 Agric 1.3 01/02/1990 Agric 1.2 01/01/1990 Food 0.9 01/02/1990 Food 0.9 

Si bien estoy seguro de que puedo hacer esto de una manera complicada, ¿hay alguna forma de hacerlo en unas pocas líneas de código?

Utilizando pd.DataFrame.melt

 df.melt('Date', var_name='Sector', value_name='Beta') Date Sector Beta 0 01/01/1990 Agric 1.3 1 01/02/1990 Agric 1.2 2 01/01/1990 Food 0.9 3 01/02/1990 Food 0.9 

Usa set_index y set_index :

 df.set_index('Date').rename_axis('Sector',axis=1).stack()\ .reset_index(name='Beta') 

Salida:

  Date Sector Beta 0 01/01/1990 Agric 1.3 1 01/01/1990 Food 0.9 2 01/02/1990 Agric 1.2 3 01/02/1990 Food 0.9 

O puedes usar lreshape

 df=pd.lreshape(df2, {'Date': ["Date","Date"], 'Beta': ['Agric', 'Food']}) df['Sector']=sorted(df2.columns.tolist()[1:3]*2) Out[654]: Date Beta Sector 0 01/01/1990 1.3 Agric 1 01/02/1990 1.2 Agric 2 01/01/1990 0.9 Food 3 01/02/1990 0.9 Food 

En caso de tener 48 columnas.

 df=pd.lreshape(df2, {'Date':['Date']*2, 'Beta': df2.columns.tolist()[1:3]}) df['Sector']=sorted(df2.columns.tolist()[1:3]*2) 

También para las columnas Sector, es más seguro crearlo por

 import itertools list(itertools.chain.from_iterable(itertools.repeat(x, 2) for x in df2.columns.tolist()[1:3])) 

EDITAR Causa lreshap no está documentado (según @ Ted Petrou Es mejor usar los métodos DataFrame disponibles si es posible y luego, si ninguno está disponible, usar las funciones documentadas. Además, este problema es un caso de uso muy sencillo para derretir o astackr. Es un mal precedente establecer para que los nuevos pandas vengan a Stack Overflow y encuentren respuestas con votaciones con lreshape.

Además, si desea saber más sobre esto, puede consultarlo en github

A continuación se muestra el método utilizando pd.wide_to_long

 dict1 = {'Agric':'A_Agric','Food':'A_Food'} df2 = df.rename(columns=dict1) pd.wide_to_long(df2.reset_index(),['A'],i='Date',j='Sector',sep='_',suffix='.').reset_index().drop('index',axis=1).rename(columns={'A':'Beta '}) Out[2149]: Date Sector Beta 0 01/01/1990 Agric 1.3 1 01/02/1990 Agric 1.2 2 01/01/1990 Food 0.9 3 01/02/1990 Food 0.9