I have two Pandas data frames: one with Daily data and one with Weekly data. I want to add the weekly data to each row of the daily data for each group of column A.
For example, for each row on the daily data frame from 2022/07/04 to 2022/07/09, I want to add the weekly data from 2022/07/04 for each group of column A and so on.
The code below reproduces the desired result:
- Generate the data
import pandas as pd
import numpy as np
def generate_df(date_range):
tf_dict = []
for A in range(0,4000):
for d in date_range:
tf_dict.append({"A":A,
**{f"B_{i}":np.random.randint(0,10) for i in range(1,250)},
"datadate": d})
return pd.DataFrame(tf_dict)
# Daily Dataframe
daily_range = pd.date_range(start='1/1/2022', end='2/15/2022', freq='D')
df_daily = generate_df(daily_range)
# Weekly Dataframe
weekly_range = pd.date_range(start='1/1/2022', end='2/15/2022', freq='W')
df_weekly = generate_df(weekly_range)
df_weekly = df_weekly.add_prefix("higher_tf_")
Note that I took a range of 4000 for A
for simplification. But with real data, A is close to 8000
- Create the date range on the weekly data frame so it makes it easier to filter on the daily data frame
dfs = []
for i, dfg in df_weekly.groupby("higher_tf_A"):
dfg = dfg.sort_values("higher_tf_datadate")
dfg["higher_tf_next_date"] = dfg["higher_tf_datadate"].shift(-1)
dfs.append(dfg)
df_weekly = pd.concat(dfs)
(I added the next date to the previous row, so I have a date range on the same row)
- For each weekly data, create a mask grouping on 'A' and the date range. Then update the daily rows with the weekly data.
%%time
for index, row in df_weekly.iterrows():
mask = (df_daily["A"]==row["higher_tf_A"]) & \
(df_daily['datadate'] >= row['higher_tf_datadate']) & \
(df_daily['datadate'] < row['higher_tf_next_date'])
df_daily.loc[mask, row.index] = row.values
Results of %%time
:
CPU times: user 1min 59s, sys: 4.34 s, total: 2min 3s Wall time: 2min 4s
How can I improve the last code to decrease execution time?
Note that the timeframes can change (e.g. Hourly and daily, minutes and hours, ...)