Home > Mobile >  Distributing values of a dictionary between keys in another dictionary
Distributing values of a dictionary between keys in another dictionary

Time:01-09

There is a dictionary like this:

cap_dict = {Timestamp('2020-06-30 00:00:00'): 40000, Timestamp('2020-09-30 00:00:00'): 52000, 
            Timestamp('2020-12-31 00:00:00'): 52000, Timestamp('2021-03-31 00:00:00'): 58000, 
            Timestamp('2021-06-30 00:00:00'): 89000, Timestamp('2021-09-30 00:00:00'): 89000
            }

I am going to create a dictionary (called daily_cap) which has daily keys between date(2020, 6, 28) and date(2022, 1, 2) (or any given date) and the values from above dictionary. In daily_cap each of the keys should use the value of the latest available month before itself. For example, 40000 should be allocated to keys from Timestamp('2020-06-30 00:00:00') to Timestamp('2020-09-29 00:00:00') and 52000 should be allocated to keys from Timestamp('2020-09-30 00:00:00') to Timestamp('2021-03-30 00:00:00'). There is another problem in the first element of cap_dict. As I mentioned, the daily_cap dictionary starts from date(2020, 6, 28) (or any given date) while the first element of cap_dict is Timestamp('2020-06-30 00:00:00'). Each day before the first element of cap_dict should get the first element of cap_dict in this situation. For example, values for the Timestamp('2020-06-28 00:00:00') and Timestamp('2020-06-29 00:00:00') should be 40000. How can I create the daily_cap dictionary?

I tried this code:

import pandas as pd
from datetime import date
from dateutil.rrule import rrule, DAILY


start_date = date(2020, 6, 28)
end_date = date(2022, 1, 2)

cap_dict = {Timestamp('2020-06-30 00:00:00'): 40000, Timestamp('2020-09-30 00:00:00'): 52000, 
            Timestamp('2020-12-31 00:00:00'): 52000, Timestamp('2021-03-31 00:00:00'): 58000, 
            Timestamp('2021-06-30 00:00:00'): 89000, Timestamp('2021-09-30 00:00:00'): 89000
            }

i = 0
daily_cap = {}
val_list = list(cap_dict.values())

for day in rrule(DAILY, dtstart=start_date, until=end_date):
    t = pd.Timestamp(day)
    if t not in cap_dict.keys():
        acceptable_value = val_list[0 i]
        val = acceptable_value
        daily_cap.update({t: val})
        i  = 1
    else:
        daily_cap.update({t: cap_dict[t]})
        i  = 1

print(daily_cap)

The above code does not work correctly since the length of val_list and days between start_date and end_date are not the same. The output should be like this:

daily_cap = {Timestamp('2020-06-28 00:00:00'): 40000, 
             Timestamp('2020-06-29 00:00:00'): 40000, 
             Timestamp('2020-06-30 00:00:00'): 40000,
             Timestamp('2020-07-01 00:00:00'): 40000, 
             .
             .
             .
             Timestamp('2021-04-27 00:00:00'): 58000,
             Timestamp('2021-04-28 00:00:00'): 58000,
             Timestamp('2021-04-29 00:00:00'): 58000,
             .
             .
             .
             Timestamp('2021-09-30 00:00:00'): 89000, 
             Timestamp('2021-10-01 00:00:00'): 89000,
             Timestamp('2021-10-02 00:00:00'): 89000
             }

CodePudding user response:

You can create a pandas series from your dict with the new range as index then use ffill and bfill:

import pandas as pd
from datetime import date

start_date = date(2020, 6, 28)
end_date = date(2022, 1, 2)

cap_dict = {pd.Timestamp('2020-06-30 00:00:00'): 40000, pd.Timestamp('2020-09-30 00:00:00'): 52000, 
            pd.Timestamp('2020-12-31 00:00:00'): 52000, pd.Timestamp('2021-03-31 00:00:00'): 58000, 
            pd.Timestamp('2021-06-30 00:00:00'): 89000, pd.Timestamp('2021-09-30 00:00:00'): 89000
            }

date_range = pd.date_range(start_date, end_date, freq='D')
daily_series = pd.Series(cap_dict, index=date_range).ffill().bfill()

daily_series.to_dict() will give you:

{Timestamp('2020-06-28 00:00:00', freq='D'): 40000.0,
 Timestamp('2020-06-29 00:00:00', freq='D'): 40000.0,
...
 Timestamp('2022-01-01 00:00:00', freq='D'): 89000.0,
 Timestamp('2022-01-02 00:00:00', freq='D'): 89000.0}
  • Related