Tengo un pandas.Dataframe
con las siguientes columnas:
a_1 ab_1 ac_1 a_2 ab_2 ac_2 2 3 4 5 6 7
¿Cómo lo convierto en lo siguiente?
a ab ac 2 3 4 5 6 7
Estaba tratando de usar pandas melt para convertir de formato ancho a largo, pero no estoy seguro de la syntax.
Puede usar split
para MultiIndex
y luego remodelar por stack
y el último uso reset_index
para eliminar MultiIndex
:
df.columns = df.columns.str.split('_', expand=True) df = df.stack().reset_index(drop=True) print (df) a ab ac 0 2 3 4 1 5 6 7
df = df.stack().reset_index(level=0, drop=True) print (df) a ab ac 1 2 3 4 2 5 6 7
Puedes reemplazar las columnas por un multi-índice y una stack:
df.columns = pd.MultiIndex.from_tuples(df.columns.str.split('_').map(tuple)) df = df.stack()
Aquí hay una forma de hacerlo:
df.columns = pd.MultiIndex.from_tuples( [c.split('_') for c in df.columns], names=['col', 'row']) df.melt().pivot(index='row', columns='col', values='value')
Cree un pandas.MultiIndex
para las columnas dividiendo en _
.
melt
el dataframe y luego pivot
sobre los elementos de los nombres de columna originales.
df = pd.DataFrame( data=[range(2, 8)], columns='a_1 ab_1 ac_1 a_2 ab_2 ac_2'.split() ) print(df) df.columns = pd.MultiIndex.from_tuples( [c.split('_') for c in df.columns], names=['col', 'row']) print(df.melt().pivot(index='row', columns='col', values='value'))
a_1 ab_1 ac_1 a_2 ab_2 ac_2 0 2 3 4 5 6 7 col a ab ac row 1 2 3 4 2 5 6 7
Si usa pandas antes de 0.20.0, melt()
como:
print(pd.melt(df).pivot(index='row', columns='col', values='value'))
Puede dividir el dataframe en dos, luego cambiar el nombre de las columnas y finalmente concatenarlas:
cols = ['a', 'ab', 'ac'] df1 = df[["a_1", "ab_1", "ac_1"]] df2 = df[["a_2", "ab_2", "ac_2"]] df1.columns = cols df2.columns = cols df3 = pd.concat([df1, df2], ignore_index=True)
Si desea usar pnd.melt
, probablemente debería usar los parámetros value_vars
y value_name
:
df_a = pnd.melt(df, value_vars=['a_1', 'a_2'], value_name='a')[['a']] df_ab = pnd.melt(df, value_vars=['ab_1', 'ab_2'], value_name='ab')[['ab']] df_ac = pnd.melt(df, value_vars=['ac_1', 'ac_2'], value_name='ac')[['ac']] df_final = df_a.join(df_b).join(df_c)
Alternativamente, tomando un enfoque más funcional:
col_prefixes = ['a', 'ab', 'ac'] df_cuts = map(lambda x: pnd.melt(df, value_vars=['%s_1' % x, '%s_2' % x], value_name=x)[[x]], col_prefixes) df_final = reduce(lambda x, y: x.join(y), df_cuts)
Hay una función incorporada wide_to_long para más información en la documentación:
In [115]: df Out[115]: a_1 ab_1 ac_1 a_2 ab_2 ac_2 0 2 3 4 5 6 7 In [116]: df['id'] = df.index In [117]: df Out[117]: a_1 ab_1 ac_1 a_2 ab_2 ac_2 id 0 2 3 4 5 6 7 0 In [118]: pd.wide_to_long(df, ['a','ab','ac'],i='id',j='num',sep='_') Out[118]: a ab ac id num 0 1 2 3 4 2 5 6 7