使用while循环进行Pandas DataFrame匹配时陷入无限循环求助
解决DataFrame嵌套循环引发的无限循环问题
首先,咱们来拆解你遇到的问题:你的代码运行后只打印了0 0就陷入无限循环,核心原因是多余的while循环内部没有更新变量j,导致条件永远成立。我先帮你分析问题,再给出修复和优化的方案。
问题代码回顾
你原本的代码整理后如下:
import pandas as pd for i in range(len(a1)): title_derived = [] k = 100000 print(i) for j in range(len(b1)): print(j) while j < (k + 6): # print(b1.iloc[i][10], a1.iloc[j][3]) if b1.iloc[j][10] == a1.iloc[i][3]: print(j,k) print('1st if ' + str(j)) print (b1.iloc[j][1], a1.iloc[i][11], b1.iloc[j][5]) if (((pd.to_datetime(b1.iloc[j][1]) <= pd.to_datetime(a1.iloc[i][11]) <= pd.to_datetime(b1.iloc[j][5]))) or ((pd.to_datetime(b1.iloc[j][1]) <= pd.to_datetime(a1.iloc[i][8]) <= pd.to_datetime(b1.iloc[j][5])))) : print('2nd if' + str(j)) title_derived.append(b1.iloc[j][15]) print('inserted ' + b1.iloc[j][15] + ' in ' + str(i) + ' th record ') a1.iat[i,65] = title_derived
无限循环的根源
看这段代码里的while j < (k + 6):
k被硬编码为100000,条件等价于j < 100006- 当
j从for循环的0开始时,进入while循环后没有任何代码修改j的值,j永远是0,满足0 < 100006的条件,导致循环永远无法退出。 - 这个
while循环完全是多余的——你的逻辑是遍历b1的每一行,不需要额外的范围限制。
修复方案:去掉多余的while循环
先给你修复基础的循环代码,解决无限循环问题,同时优化重复的日期转换操作(避免每次循环都调用pd.to_datetime,提升效率):
import pandas as pd # 提前预处理日期列,避免循环内重复转换,大幅提升效率 b1['start_date'] = pd.to_datetime(b1.iloc[:, 1]) b1['end_date'] = pd.to_datetime(b1.iloc[:, 5]) a1['target_date1'] = pd.to_datetime(a1.iloc[:, 11]) a1['target_date2'] = pd.to_datetime(a1.iloc[:, 8]) for i in range(len(a1)): title_derived = [] print(f"Processing a1 row {i}") # 提前取出当前a1行的关键值,减少重复索引 a_match_val = a1.iloc[i, 3] a_date1 = a1.loc[i, 'target_date1'] a_date2 = a1.loc[i, 'target_date2'] for j in range(len(b1)): print(f"Checking b1 row {j}") # 第一个匹配条件:b1第11列(iloc[j,10])等于a1第4列(iloc[i,3]) if b1.iloc[j, 10] == a_match_val: print(f"Matched value at b1 row {j}") b_start = b1.loc[j, 'start_date'] b_end = b1.loc[j, 'end_date'] # 第二个日期区间条件 if (b_start <= a_date1 <= b_end) or (b_start <= a_date2 <= b_end): print(f"Date condition satisfied at b1 row {j}") matched_title = b1.iloc[j, 15] title_derived.append(matched_title) print(f"Added '{matched_title}' to a1 row {i}") # 将结果赋值到a1的第66列(索引65) a1.iat[i, 65] = title_derived
更高效的优化:用Pandas向量操作替代嵌套循环
上面的循环代码虽然能解决问题,但对于大尺寸的DataFrame来说效率极低——Pandas的核心优势是向量化操作,避免逐行遍历。这里给你推荐更高效的实现方式:
import pandas as pd # 预处理日期列 b1['start_date'] = pd.to_datetime(b1.iloc[:, 1]) b1['end_date'] = pd.to_datetime(b1.iloc[:, 5]) a1['target_date1'] = pd.to_datetime(a1.iloc[:, 11]) a1['target_date2'] = pd.to_datetime(a1.iloc[:, 8]) # 定义函数:对a1的每一行,找到b1中满足条件的标题 def get_matching_titles(row): # 构建筛选条件 mask = (b1.iloc[:, 10] == row.iloc[3]) & \ ((b1['start_date'] <= row['target_date1']) & (row['target_date1'] <= b1['end_date']) | \ (b1['start_date'] <= row['target_date2']) & (row['target_date2'] <= b1['end_date'])) # 返回匹配的标题列表 return b1.loc[mask, b1.columns[15]].tolist() # 应用函数到a1的每一行,赋值到目标列 a1.iloc[:, 65] = a1.apply(get_matching_titles, axis=1)
这个方法利用apply和布尔索引,比嵌套循环快得多,代码也更简洁易维护。
内容的提问来源于stack exchange,提问作者Sarang Manjrekar
相关产品推荐
相关产品推荐

