如何根据两个日期间的周数重复Pandas DataFrame行?
问题:按周数重复DataFrame行并生成连续周数
原始数据
import pandas as pd df = pd.DataFrame( { 'ID': ['ID001', 'ID002', 'ID003'], 'DATE': ['24/12/2023', '01/02/2024', '12/02/2024'], } ) df['DATE'] = pd.to_datetime(df['DATE'], dayfirst=True) print(df)
输出:
ID DATE 0 ID001 2023-12-24 1 ID002 2024-02-01 2 ID003 2024-02-12
需求
为每个ID重复N次行,N是DATE列与当前日期之间的周数;每行需对应从DATE所在周开始,到当前周的连续周数,同时匹配周对应的年份。
错误尝试代码及输出
number_of_weeks = (pd.Timestamp('now') - df['DATE']).dt.days // 7 final = df.copy() final['YEAR'] = final['DATE'].dt.isocalendar().year final['WEEK'] = final['DATE'].dt.isocalendar().week final['WEEKS'] = (pd.Timestamp('now') - df['DATE']).dt.days // 7 for index, row in final.iterrows(): for i in range(1, row['WEEKS'] + 1): final.loc[i, 'WEEK'] = i final = final.ffill().drop(columns='WEEKS') print(final)
输出:
ID DATE YEAR WEEK 0 ID001 2023-12-24 2023 51 1 ID002 2024-02-01 2024 1 2 ID003 2024-02-12 2024 2 3 ID003 2024-02-12 2024 3 4 ID003 2024-02-12 2024 4 5 ID003 2024-02-12 2024 5 6 ID003 2024-02-12 2024 6 7 ID003 2024-02-12 2024 7
正确解决方案
原问题出在没有为每个ID新增行,而是直接覆盖现有索引的WEEK值。正确做法是为每个ID生成包含连续周数的序列,再合并到原数据中:
import pandas as pd # 原始数据处理 df = pd.DataFrame( { 'ID': ['ID001', 'ID002', 'ID003'], 'DATE': ['24/12/2023', '01/02/2024', '12/02/2024'], } ) df['DATE'] = pd.to_datetime(df['DATE'], dayfirst=True) # 获取当前日期的ISO周信息 current_date = pd.Timestamp('now') current_year, current_week, _ = current_date.isocalendar() # 为每行生成周数序列 def generate_week_series(row): start_year, start_week, _ = row['DATE'].isocalendar() weeks_list = [] # 分情况处理跨年份的周数生成 if start_year == current_year: weeks = list(range(start_week, current_week + 1)) weeks_list.extend([(start_year, w) for w in weeks]) else: # 处理起始年剩余的周 weeks_remaining = list(range(start_week, 53)) weeks_list.extend([(start_year, w) for w in weeks_remaining if pd.Timestamp.fromisocalendar(start_year, w, 1) <= current_date]) # 处理中间年份的所有周(如果有的话) for year in range(start_year + 1, current_year): weeks_list.extend([(year, w) for w in range(1, 53)]) # 处理当前年的周 weeks_current = list(range(1, current_week + 1)) weeks_list.extend([(current_year, w) for w in weeks_current]) # 生成对应行的重复数据 rows = [] for year, week in weeks_list: rows.append({ 'ID': row['ID'], 'DATE': row['DATE'], 'YEAR': year, 'WEEK': week }) return pd.DataFrame(rows) # 应用函数并合并结果 final_df = pd.concat([generate_week_series(row) for _, row in df.iterrows()], ignore_index=True) print(final_df)
说明
- 先获取当前日期的ISO周年份和周数,确保序列截止到当前周
- 针对每个ID的起始日期,分情况处理跨年份的周数:
- 同一年份直接生成从起始周到当前周的连续序列
- 跨年份则分别处理起始年剩余周、中间年份全周、当前年的周
- 为每个周生成对应的行,保留原始ID和DATE,匹配对应周的YEAR和WEEK
预期输出示例(以当前周为2024年第7周为例)
ID DATE YEAR WEEK 0 ID001 2023-12-24 2023 51 1 ID001 2023-12-24 2023 52 2 ID001 2023-12-24 2024 1 3 ID001 2023-12-24 2024 2 4 ID001 2023-12-24 2024 3 5 ID001 2023-12-24 2024 4 6 ID001 2023-12-24 2024 5 7 ID001 2023-12-24 2024 6 8 ID001 2023-12-24 2024 7 9 ID002 2024-02-01 2024 5 10 ID002 2024-02-01 2024 6 11 ID002 2024-02-01 2024 7 12 ID003 2024-02-12 2024 7
内容的提问来源于stack exchange,提问作者VERBOSE
相关产品推荐
相关产品推荐

