从多年度日Dataframe生成周Dataframe的跨年分组问题
问题:跨年周数据拆分异常(2018年12月31日单独成周)
基于2016-2022年的日度Dataframe生成周度数据时,现有代码整体运行正常,但2018年12月31日被单独划分为一周,实际该日期应归入2019年1月4日结束的周,求修复方案。
日度Dataframe:
| Date | Open | High | Low | Close |
|---|---|---|---|---|
| 24-Dec-2018 | 26925 | 26982.6 | 26737.1 | 26810 |
| 26-Dec-2018 | 26700 | 27070 | 26439.6 | 27067.8 |
| 27-Dec-2018 | 27198 | 27260 | 26860 | 26877.6 |
| 28-Dec-2018 | 27155 | 27350 | 27051.05 | 27290 |
| 31-Dec-2018 | 27400 | 27429.5 | 27242.1 | 27318 |
| 01-Jan-2019 | 27300.2 | 27532 | 27135 | 27526 |
| 02-Jan-2019 | 27410.3 | 27523 | 27175.1 | 27275.3 |
| 03-Jan-2019 | 27260 | 27319.4 | 27062.3 | 27076 |
| 04-Jan-2019 | 27169 | 27431 | 27058 | 27376 |
| 07-Jan-2019 | 27555 | 27586.75 | 27375 | 27382.2 |
| 08-Jan-2019 | 27388.4 | 27632.65 | 27292 | 27610.2 |
| 09-Jan-2019 | 27752.2 | 27784.4 | 27451.4 | 27752 |
| 10-Jan-2019 | 27720.3 | 27740 | 27587.1 | 27630.05 |
| 11-Jan-2019 | 27675 | 27689.9 | 27502.55 | 27533 |
| 14-Jan-2019 | 27465 | 27480 | 27300.95 | 27347.6 |
| 15-Jan-2019 | 27410.6 | 27539 | 27392.1 | 27520 |
现有代码输出:
| Date | weekday | Open | High | Low | Close |
|---|---|---|---|---|---|
| 21-Dec-2018 | Friday | 26988.8 | 27425 | 26888.6 | 26971.8 |
| 28-Dec-2018 | Friday | 26925 | 27350 | 26439.6 | 27290 |
| 31-Dec-2018 | Monday | 27400 | 27429.5 | 27242.1 | 27318 |
| 04-Jan-2019 | Friday | 27300.2 | 27532 | 27058 | 27376 |
| 11-Jan-2019 | Friday | 27555 | 27784.4 | 27292 | 27533 |
| 18-Jan-2019 | Friday | 27465 | 27676 | 27300.95 | 27560 |
| 25-Jan-2019 | Friday | 27560.05 | 27674.95 | 27067 | 27158.95 |
当前使用的代码:
temp_df = daily_df.copy() temp_df['Date'] = pd.to_datetime(temp_df['Date'], format='%d-%b-%Y') weekly_data = temp_df.assign(wk=temp_df['Date'].dt.isocalendar().week, ye=temp_df['Date'].dt.year, iso_ye=temp_df['Date'].dt.isocalendar().year).groupby(['wk', 'ye', 'iso_ye']).aggregate({'Date': ['max'], 'Open': ['first'],'High': ['max'], 'Low': ['min'], 'Close': ['last']}).reset_index() # check if maximum date in week is in previous year weekly_data.loc[weekly_data['Date', 'max'].dt.year != weekly_data['iso_ye'], 'wk'] = 1 weekly_data.columns = weekly_data.columns.droplevel(1) weekly_data = weekly_data.sort_values(by=['Date']).drop(columns=['ye', 'iso_ye']).reset_index(drop=True) weekly_data['weekday'] = weekly_data['Date'].dt.day_name() weekly_data['Date'] = pd.to_datetime(weekly_data['Date'], format='%Y%m%d') weekly_data['Date'] = weekly_data['Date'].dt.strftime('%d-%b-%Y') weekly_data.drop(['wk'], axis=1) weekly_data = weekly_data.reindex(columns=['Date', 'weekday', 'Open', 'High', 'Low', 'Close']) weekly_data
解决方案
问题根源在于原代码同时用公历年份(ye)和ISO周+ISO年份分组,导致2018年12月31日(ISO周属于2019年第1周,但公历年份是2018)被单独拆分。正确做法是直接用ISO年份和ISO周作为唯一分组键,完全对齐ISO周的规则。
修改后的代码:
temp_df = daily_df.copy() temp_df['Date'] = pd.to_datetime(temp_df['Date'], format='%d-%b-%Y') # 直接使用ISO年份和ISO周分组,避免公历年份干扰 weekly_data = temp_df.assign( iso_year=temp_df['Date'].dt.isocalendar().year, iso_week=temp_df['Date'].dt.isocalendar().week ).groupby(['iso_year', 'iso_week']).aggregate({ 'Date': ['max'], 'Open': ['first'], 'High': ['max'], 'Low': ['min'], 'Close': ['last'] }).reset_index() # 处理列名和格式 weekly_data.columns = weekly_data.columns.droplevel(1) weekly_data = weekly_data.sort_values(by=['Date']).drop(columns=['iso_year', 'iso_week']).reset_index(drop=True) weekly_data['weekday'] = weekly_data['Date'].dt.day_name() weekly_data['Date'] = weekly_data['Date'].dt.strftime('%d-%b-%Y') weekly_data = weekly_data.reindex(columns=['Date', 'weekday', 'Open', 'High', 'Low', 'Close']) weekly_data
修改后预期输出
| Date | weekday | Open | High | Low | Close |
|---|---|---|---|---|---|
| 21-Dec-2018 | Friday | 26988.8 | 27425 | 26888.6 | 26971.8 |
| 28-Dec-2018 | Friday | 26925 | 27350 | 26439.6 | 27290 |
| 04-Jan-2019 | Friday | 27400 | 27532 | 27058 | 27376 |
| 11-Jan-2019 | Friday | 27555 | 27784.4 | 27292 | 27533 |
| 18-Jan-2019 | Friday | 27465 | 27676 | 27300.95 | 27560 |
| 25-Jan-2019 | Friday | 27560.05 | 27674.95 | 27067 | 27158.95 |
可以看到,2018年12月31日已经和2019年1月1-4日合并为同一周,周结束日期显示为2019年1月4日,Open取该周第一个交易日(12月31日)的数值,其他字段也按周维度正确聚合。
内容的提问来源于stack exchange,提问作者vineet singh
相关产品推荐
相关产品推荐

