I have a pandas data frame which has the data sorted into quarters like this: ( I am showing a sample data)
df
id qtr value
a Q01 100
a Q02 130
a Q03 160
a Q04 100
b Q01 1000
b Q02 1300
b Q03 1600
b Q04 1000
Now the problem what I want to solve is to redistribute the quarter values to months as follows: I want to distribute the quarter value into 3 and assign first two months that value and the remaining to the last month in the quarter. So my output should be like follows
outdf
id qtr mnth value
a Q01 M01 30
a Q01 M02 30
a Q01 M03 40
a Q02 M04 40
a Q02 M05 40
a Q02 M06 50
a Q03 M07 50
a Q03 M08 50
a Q03 M09 60
a Q04 M10 30
a Q04 M11 30
a Q04 M12 40
b Q01 M01 300
b Q01 M02 300
b Q01 M03 400
b Q02 M04 400
b Q02 M05 400
b Q02 M06 500
b Q03 M07 500
b Q03 M08 500
b Q03 M09 600
b Q04 M10 300
b Q04 M11 300
b Q04 M12 400
So what I till now tried is as follows:
I created a mapping for quarters:
quarters = {'Q01': ['M01','M02','M03'], 'Q02': ['M04','M05','M06'],
'Q03': ['M07','M08','M09'], 'Q04': ['M10', 'M11', 'M12']}
and the tried to melt and explode the dataframe using this trick:
out = (df.melt(['id'], value_name='value', var_name='qtr')
.assign(rev=lambda d: d['value'],#.div(3),
qtr=lambda d: d['qtr'].str[-2:].map(quarters)
).explode('qtr'))
Unfortunately its not doing what I want. Any help as to how to achieve my output will be helpful and appreciated.
Just tried solving them in a little lengthy way. Hope this approach helps!
For now, I am using some custom roundings but, i hope you can continue from this
Below is the code
import pandas as pd
data = {'id': ['a', 'a', 'a', 'a', 'b', 'b', 'b', 'b'],
'qtr': ['Q01', 'Q02', 'Q03', 'Q04', 'Q01', 'Q02', 'Q03', 'Q04'],
'value': [100, 130, 160, 100, 1000, 1300, 1600, 1000]}
df = pd.DataFrame(data)
quarters_to_months = {
'Q01': ['M01', 'M02', 'M03'],
'Q02': ['M04', 'M05', 'M06'],
'Q03': ['M07', 'M08', 'M09'],
'Q04': ['M10', 'M11', 'M12']
}
result_df = pd.DataFrame(columns=['id', 'qtr', 'mnth', 'value'])
for _, row in df.iterrows():
qtr = row['qtr']
months = quarters_to_months[qtr]
for i, month in enumerate(months):
if i == 2:
result_df = pd.concat([result_df,pd.DataFrame({'id': row['id'], 'qtr': qtr, 'mnth': month, 'value': (row['value'] * 0.4)}, index=[0])], ignore_index=True)
else:
result_df = pd.concat([result_df,pd.DataFrame({'id': row['id'], 'qtr': qtr, 'mnth': month, 'value': (row['value'] * 0.3)}, index=[0])], ignore_index=True)
result_df.sort_values(by=['id', 'qtr', 'mnth'], inplace=True)
result_df.reset_index(drop=True, inplace=True)
def custom_round(value):
if(value>100):
return round(value, -2)
else:
return round(value, -1)
result_df['value'] = result_df['value'].apply(custom_round)
print(result_df)
Output