Home > Software engineering >  Unpivot a DataFrame by month year elements
Unpivot a DataFrame by month year elements

Time:03-01

I have the following table:

Index Name Value1 Value2 Value3
1 abc 136 137 169
2 cde 164 190 126
3 edf 130 179 136
4 mno 181 108 165

The Value columns correspond to Years 2021-2019. I want to duplicate each value for every month of the corresponding year. In other words, I want to restructure it into a DataFrame like this:

Index Name Month Year Value
1 abc 1 2021 136
1 abc 2 2021 136
1 abc 3 2021 136
1 abc 4 2021 136
1 abc 5 2021 136
1 abc 6 2021 136
1 abc 7 2021 136
1 abc 8 2021 136
1 abc 9 2021 136
1 abc 10 2021 136
1 abc 11 2021 136
1 abc 12 2021 136
1 abc 1 2020 137
1 abc 2 2020 137
1 abc 3 2020 137
1 abc 4 2020 137
1 abc 5 2020 137
1 abc 6 2020 137
1 abc 7 2020 137
1 abc 8 2020 137
1 abc 9 2020 137
1 abc 10 2020 137
1 abc 11 2020 137
1 abc 12 2020 137
1 abc 1 2019 169
1 abc 2 2019 169
1 abc 3 2019 169
1 abc 4 2019 169
1 abc 5 2019 169
1 abc 6 2019 169
... ... ... ... ...

CodePudding user response:

Let's try with melt assign and explode "Month":

out = (pd.melt(df.rename(columns={'Value1':2021, 'Value2':2020, 'Value3':2019}), 
               id_vars=['Index','Name'], value_vars=[2021, 2020, 2019], 
               var_name='Year', value_name='Value')
       .assign(Month=pd.Series([[*range(1,13)]])).ffill()
       .explode('Month')
       [['Index','Name','Month','Year','Value']]
       .sort_values(by=['Index','Name','Year'], ascending=[True, True, False])
       .reset_index(drop=True)
      )

Output:

     Index Name Month  Year  Value
0        1  abc     1  2021    136
1        1  abc     2  2021    136
2        1  abc     3  2021    136
3        1  abc     4  2021    136
4        1  abc     5  2021    136
..     ...  ...   ...   ...    ...
139      4  mno     8  2019    165
140      4  mno     9  2019    165
141      4  mno    10  2019    165
142      4  mno    11  2019    165
143      4  mno    12  2019    165

[144 rows x 5 columns]
  • Related