Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pandas reshaping/transform the dataframe

I have dataframe df:

col_name    col_month   col_value
abc         2021-01-31  233
abc         2021-02-28  784
abc         2021-03-31  7868
def         2021-02-28  3652
def         2021-03-31  344
def         2021-04-30  87

I need the result as:

col_name    NAME        col1          col2            col3  
abc         col_month   2021-01-31    2021-02-28      2021-03-31
abc         col_value   233           784             7868
def         col_month   2021-02-28    2021-03-31      2021-04-30
def         col_value   3652          344             87

what i have tried so far using melt:

pd.melt(df, id_vars=['col_name'], var_name = 'NAME', value_name = 'VALUE')

this give the result:

col_name    NAME        VALUE
abc     col_month   2021-01-31
abc     col_month   2021-02-28
abc     col_month   2021-03-31
def     col_month   2021-02-28
def     col_month   2021-03-31
def     col_month   2021-04-30
abc     col_value   233
abc     col_value   784
abc     col_value   7868
def     col_value   3652
def     col_value   344
def     col_value   87

but i am not still able to get the desired result

like image 934
sparkstars Avatar asked Aug 16 '26 15:08

sparkstars


2 Answers

Here's another way:

df.assign(cols=df.groupby('col_name').cumcount()+1)\
  .set_index(['col_name','cols'])\
  .rename_axis('NAME', axis=1)\
  .stack().unstack(1)\
  .add_prefix('col')\
  .reset_index()

Output:

cols col_name       NAME        col1        col2        col3
0         abc  col_month  2021-01-31  2021-02-28  2021-03-31
1         abc  col_value         233         784        7868
2         def  col_month  2021-02-28  2021-03-31  2021-04-30
3         def  col_value        3652         344          87

Or with, melt:

df.assign(cols=df.groupby('col_name').cumcount()+1)\
  .melt(['col_name', 'cols'], var_name='NAME')\
  .set_index(['col_name', 'NAME', 'cols'])\
  .unstack()['value'].add_prefix('col')\
  .reset_index()
like image 187
Scott Boston Avatar answered Aug 18 '26 05:08

Scott Boston


Try using groupby and T:

>>> df.groupby('col_name').apply(lambda x: x.drop('col_name', axis=1).reset_index(drop=True).T.rename_axis(index='NAME')).rename(lambda x: f'col{x + 1}', axis=1).reset_index()
  col_name       NAME        col1        col2        col3
0      abc  col_month  2021-01-31  2021-02-28  2021-03-31
1      abc  col_value         233         784        7868
2      def  col_month  2021-02-28  2021-03-31  2021-04-30
3      def  col_value        3652         344          87
>>> 

Or try melt with pivot_table:

>>> x = df.melt('col_name')
>>> d = {'': ['col_name', 'NAME']}
>>> x.assign(idx=x.groupby(['col_name', 'variable']).cumcount()).pivot_table(index=['col_name', 'variable'], columns='idx', aggfunc=sum).reset_index().droplevel(0, axis=1).rename_axis(columns=None).rename(lambda x: f'col{x + 1}' if isinstance(x, int) else x, axis=1).rename(columns=lambda x: d.get(x, [x]).pop(0))
  col_name       NAME        col1        col2        col3
0      abc  col_month  2021-01-31  2021-02-28  2021-03-31
1      abc  col_value         233         784        7868
2      def  col_month  2021-02-28  2021-03-31  2021-04-30
3      def  col_value        3652         344          87
>>> 
like image 44
U12-Forward Avatar answered Aug 18 '26 06:08

U12-Forward



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!