基于Date_2列日期条件创建新DataFrame的技术求助
需求背景与现有数据
现有DataFrame结构如下:
Date_1 Type_1 Qty_1 Date_2 Type_2 Qty_2 29-12-2023 A 1 01-01-2024 B 2 29-12-2023 A 3 01-01-2024 B 4 30-12-2023 A 2 01-01-2024 B 3 30-12-2023 A 5 02-01-2024 B 5 31-12-2023 A 10 02-01-2024 B 6 31-12-2023 A 2 03-01-2024 B 1 01-01-2024 A 1 04-01-2023 B 2
核心需求
需针对Date_2列的唯一日期值执行以下逻辑,创建新DataFrame:
- 若该日期为周一:提取
Date_1列中该日期前三天的所有Type_1、Qty_1数据,追加该日期对应的所有Type_2、Qty_2数据; - 若为其他日期:提取
Date_1列中该日期前一天的所有Type_1、Qty_1数据,追加该日期对应的所有Type_2、Qty_2数据。
现状与问题
已编写部分Python代码但陷入瓶颈,代码如下:
from datetime import datetime, timedelta # Function to find previous three dates for a given date def get_previous_three_dates(date): return [date - timedelta(days=i) for i in range(1, 4)] #Function to get Type and Value for previous three dates if the given date is Monday def get_type_value_for_previous_dates(df, column_name): result = [] for index, row in df.iterrows(): if row[column_name].weekday() == 0: # Check if the date is Monday (Monday corresponds to 0) previous_dates = get_previous_three_dates(row[column_name]) for prev_date in previous_dates: # Check if the previous date exists in the DataFrame if prev_date in df['Date_1'].values: entry = df[df['Date_1'] == prev_date][['Type_1', 'Sales_1']].iloc[0].to_dict() result.append({ 'Date': prev_date, 'Type': entry['Type_1'], 'Qty': entry['Sales_1']}) return result
解决思路与完整实现
关键优化点
- 优先统一日期格式:将
Date_1和Date_2转换为datetime类型,避免字符串匹配错误; - 避免重复处理:提取
Date_2的唯一值进行遍历,减少冗余计算; - 用Pandas向量操作替代行遍历:提升效率同时简化逻辑。
完整代码
import pandas as pd from datetime import datetime, timedelta # 初始化示例数据(实际场景可替换为读取数据源) data = { 'Date_1': ['29-12-2023', '29-12-2023', '30-12-2023', '30-12-2023', '31-12-2023', '31-12-2023', '01-01-2024'], 'Type_1': ['A', 'A', 'A', 'A', 'A', 'A', 'A'], 'Qty_1': [1, 3, 2, 5, 10, 2, 1], 'Date_2': ['01-01-2024', '01-01-2024', '01-01-2024', '02-01-2024', '02-01-2024', '03-01-2024', '04-01-2024'], 'Type_2': ['B', 'B', 'B', 'B', 'B', 'B', 'B'], 'Qty_2': [2, 4, 3, 5, 6, 1, 2] } df = pd.DataFrame(data) # 转换日期格式为datetime类型 df['Date_1'] = pd.to_datetime(df['Date_1'], format='%d-%m-%Y') df['Date_2'] = pd.to_datetime(df['Date_2'], format='%d-%m-%Y') # 存储最终结果的空DataFrame final_df = pd.DataFrame() # 遍历Date_2的每个唯一日期 for target_date in df['Date_2'].unique(): # 提取当前目标日期对应的Type_2、Qty_2数据,统一列名 type2_part = df[df['Date_2'] == target_date][['Type_2', 'Qty_2']].rename(columns={'Type_2': 'Type', 'Qty_2': 'Qty'}) type2_part['Data_Source'] = 'Type_2' # 可选:标记数据来源,方便验证 # 判断目标日期是否为周一 if target_date.weekday() == 0: # 计算前三天的日期范围(含起始和结束) start_prev = target_date - timedelta(days=3) end_prev = target_date - timedelta(days=1) # 提取Date_1在该范围内的Type_1、Qty_1数据 type1_part = df[(df['Date_1'] >= start_prev) & (df['Date_1'] <= end_prev)][['Type_1', 'Qty_1']].rename(columns={'Type_1': 'Type', 'Qty_1': 'Qty'}) else: # 计算前一天的日期 prev_day = target_date - timedelta(days=1) # 提取Date_1等于该日期的Type_1、Qty_1数据 type1_part = df[df['Date_1'] == prev_day][['Type_1', 'Qty_1']].rename(columns={'Type_1': 'Type', 'Qty_1': 'Qty'}) type1_part['Data_Source'] = 'Type_1' # 可选:标记数据来源 # 合并当前目标日期的两部分数据 current_result = pd.concat([type1_part, type2_part], ignore_index=True) # 添加目标日期列,明确每条数据对应的Date_2日期 current_result['Target_Date'] = target_date # 追加到最终结果 final_df = pd.concat([final_df, current_result], ignore_index=True) # 打印最终结果 print(final_df)
代码说明
- 日期转换确保了日期比较的准确性,避免因字符串格式不一致导致的匹配失败;
- 用
unique()处理Date_2,避免对同一日期重复执行逻辑; - 统一列名后用
concat()合并数据,保证结果结构一致; - 可选的
Data_Source列用于区分数据来自Type_1还是Type_2,便于后续验证和分析。
内容的提问来源于stack exchange,提问作者Romi
相关产品推荐
相关产品推荐

