Pandas Derretir varios grupos de columnas en varias columnas de destino por nombre

Me gustaría fundir varios grupos de columnas de un dataframe en varias columnas de destino. Similar a las preguntas Python Pandas Melt Grupos de columnas iniciales en múltiples columnas de destino y pandas dataframe remodelación / astackmiento de múltiples variables de valor en columnas separadas . Sin embargo, necesito hacer esto explícitamente por nombre de columna, en lugar de por ubicación de índice.

import pandas as pd df = pd.DataFrame([('a','b','c',1,2,3,'aa','bb','cc'), ('d', 'e', 'f', 4, 5, 6, 'dd', 'ee', 'ff')], columns=['a_1', 'a_2', 'a_3','b_1', 'b_2', 'b_3','c_1', 'c_2', 'c_3']) df 

Marco de datos original:

  id a_1 a_2 a_3 b_1 b_2 b_3 c_1 c_2 c_3 0 101 abc 1 2 3 aa bb cc 1 102 def 4 5 6 dd ee ff 

Marco de datos objective

  id abc 0 101 a 1 aa 1 101 b 2 bb 2 101 c 3 cc 3 102 d 4 dd 4 102 e 5 ee 5 102 f 6 ff 

El consejo es muy apreciado en un acercamiento a esto.

Hay una manera más eficiente de resolver este tipo de problemas que involucran la fusión de múltiples conjuntos diferentes de columnas. pd.wide_to_long está diseñado para estas situaciones exactas.

 pd.wide_to_long(df, stubnames=['a', 'b', 'c'], i='id', j='dropme', sep='_')\ .reset_index()\ .drop('dropme', axis=1)\ .sort_values('id') id abc 0 101 a 1 aa 2 101 b 2 bb 4 101 c 3 cc 1 102 d 4 dd 3 102 e 5 ee 5 102 f 6 ff 

Puede convertir los nombres de las columnas en un índice múltiple en función del patrón de columnas y luego astackr a un nivel particular según el resultado que necesite:

 import pandas as pd df.set_index('id', inplace=True) df.columns = pd.MultiIndex.from_tuples(tuple(df.columns.str.split("_"))) df.stack(level = 1).reset_index(level = 1, drop = True).reset_index() # id abc #101 a 1 aa #101 b 2 bb #101 c 3 cc #102 d 4 dd #102 e 5 ee #102 f 6 ff 
 cols = df.columns.difference(['id']) pd.lreshape(df, cols.groupby(cols.str.split('_').str[0])).sort_values('id') Out: id acb 0 101 a aa 1 2 101 b bb 2 4 101 c cc 3 1 102 d dd 4 3 102 e ee 5 5 102 f ff 6