Python优化DataFrame嵌套循环及解决数据分片报错问题
问题与解决方案
问题说明
- 执行以下嵌套for循环时出现无限循环:
for i in df2.index: for j in df1.F_Date: A0=df2['X'][i] A1=df2['Y'][i] A1=df2['Z'][i] # 笔误:覆盖了A1的值 df1.loc[(df1['ID'] == A0) & (df1['F_Date'] ==j ), 'Rule'] = 'A0 Occuar' df1.loc[(df1['ID'] == A1) & (df1['F_Date'] ==j ), 'Rule'] = 'A1 Occuar' df1.loc[(df1['ID'] == A2) & (df1['F_Date'] ==j ), 'Rule'] = 'A2 Occuar' # A2未定义,会报错
- 使用
np.array_split拆分df1后执行for j in split_df.F_Date:报错:AttributeError: 'list' object has no attribute 'F_Date' - 实际需求:遍历df1的每个日期和df2的每一行,检查X、Y、Z是否在该日期出现,若出现则计算X、Y的最大
Clear_Date与Z的Clear_Date的时间差,输出对应结果
示例数据
df1:
| ID | F_Date | Clear_Date |
|---|---|---|
| AB | 2023-10-01 | 2023-10-02 |
| CD | 2023-10-02 | 2023-10-03 |
| EF | 2023-10-02 | 2023-10-04 |
df2:
| X | Y | Z |
|---|---|---|
| AB | CD | EF |
| CD | AB | EF |
| EF | AB | CD |
预期输出
| X | Y | Z | Time_Difference |
|---|---|---|---|
| AB | CD | EF | 25:00 |
| CD | AB | EF | 28:00 |
| EF | AB | CD | 02:30 |
问题原因分析
- 嵌套循环问题:
- 代码存在笔误:
A1=df2['Z'][i]覆盖了Y列的值,且A2未定义,执行会直接报错 - 遍历
df1.F_Date会重复遍历所有日期行(包括重复日期),数据量大时会导致程序长时间运行,被误认为无限循环 - 循环中频繁修改df1,效率极低,且可能引发索引异常
- 代码存在笔误:
- 拆分df1报错问题:
np.array_split(df1, 20)返回的是由20个子DataFrame组成的列表,不是单个DataFrame,因此无法直接通过split_df.F_Date访问列,需遍历列表中的每个子DataFrame
解决方案
使用Pandas字典映射替代嵌套循环,提升效率并避免异常:
代码实现
import pandas as pd # 构造示例数据(实际使用时替换为你的真实数据) df1 = pd.DataFrame({ 'ID': ['AB', 'CD', 'EF'], 'F_Date': ['2023-10-01', '2023-10-02', '2023-10-02'], 'Clear_Date': ['2023-10-02', '2023-10-03', '2023-10-04'] }) # 转换日期列为datetime类型,方便计算时间差 df1['F_Date'] = pd.to_datetime(df1['F_Date']) df1['Clear_Date'] = pd.to_datetime(df1['Clear_Date']) df2 = pd.DataFrame({ 'X': ['AB', 'CD', 'EF'], 'Y': ['CD', 'AB', 'AB'], 'Z': ['EF', 'EF', 'CD'] }) # 构建(F_Date, ID)到Clear_Date的映射字典,快速查找 date_id_clear_map = df1.set_index(['F_Date', 'ID'])['Clear_Date'].to_dict() results = [] # 遍历df2的每一行 for _, row in df2.iterrows(): x, y, z = row['X'], row['Y'], row['Z'] # 遍历df1中的所有唯一日期 for date in df1['F_Date'].unique(): # 检查X、Y、Z在当前日期是否都存在 if (date, x) in date_id_clear_map and (date, y) in date_id_clear_map and (date, z) in date_id_clear_map: # 获取对应的Clear_Date x_clear = date_id_clear_map[(date, x)] y_clear = date_id_clear_map[(date, y)] z_clear = date_id_clear_map[(date, z)] # 计算X、Y的最大时间与Z的时间差 max_xy_clear = max(x_clear, y_clear) time_diff = max_xy_clear - z_clear # 转换为"小时:分钟"格式 total_hours = time_diff.days * 24 + time_diff.seconds // 3600 total_minutes = (time_diff.seconds % 3600) // 60 time_diff_str = f"{total_hours:02d}:{total_minutes:02d}" # 将结果加入列表 results.append({ 'X': x, 'Y': y, 'Z': z, 'Time_Difference': time_diff_str }) # 转换为结果DataFrame result_df = pd.DataFrame(results) print(result_df)
代码说明
- 用字典映射替代循环查找,大幅提升效率
- 遍历唯一日期而非所有日期行,避免重复计算
- 避免在循环中修改原DataFrame,减少异常风险
- 时间差计算逻辑清晰,格式化为需求的"小时:分钟"样式
内容的提问来源于stack exchange,提问作者asmaa mahmoud
相关产品推荐
相关产品推荐

