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]