使用itertools替代DataFrame嵌套for循环时结果异常,如何解决?
用itertools遍历DataFrame时结果异常的问题解决
问题描述
我有一个DataFrame,希望通过函数遍历判断每行所有元素是否处于指定的min和max区间内。嵌套for循环的实现可以正常得到预期结果,但改用itertools.product时,仅向结果列表list中添加了一个False值,不符合预期。
预期结果:
list = [False, True, True, False](每行是否全在区间内的判断结果)list2 = [(0, 0), (0, 1), (0, 3), (3, 2), (3, 3)](不在区间内的元素坐标,这部分在itertools实现中结果正确)
正常运行的嵌套循环实现
columns = len(df_test.columns) rows = len(df_test.index) list = [] list2 = [] def inRange(df, min, max): for i in range(rows): x = 0 for j in range(columns): if df_test.iloc[i, j] >= min and df_test.iloc[i, j] <= max: x = x + 1 else: list2.append((i, j)) if x == columns: list.insert(i, "True") else: list.insert(i, "False")
结果异常的itertools实现
def inRange(df, min, max): x = 0 # i = index, j = columns for i, j in itertools.product(range(rows), range(columns)): if df_test.iloc[i, j] >= min and df_test.iloc[i, j] <= max: x = x + 1 else: list2.append((i, j)) if x == columns: list.insert(i, "True") else: list.insert(i, "False")
问题原因
问题出在计数器x的初始化位置和循环逻辑:
- 嵌套循环中,
x在每行循环(for i in range(rows))内初始化,用于统计当前行符合条件的元素数量;而itertools实现里x在整个循环外初始化,变成了统计所有行符合条件的总元素数,完全偏离了每行单独统计的逻辑。 - 嵌套循环是每行遍历完所有列后,判断当前行是否全符合条件并添加结果;但itertools的循环一次性遍历所有行列组合,循环结束后只执行了一次结果插入,自然只会得到一个元素。
修正后的itertools实现
方式一:跟踪行切换逻辑
严格用itertools.product遍历所有行列组合,同时跟踪行的切换,确保每行单独统计:
import itertools columns = len(df_test.columns) rows = len(df_test.index) list = [] list2 = [] def inRange(df, min_val, max_val): # 避免和内置函数min/max重名 current_row = -1 x = 0 for i, j in itertools.product(range(rows), range(columns)): # 切换到新行时,处理上一行结果并重置计数器 if i != current_row: if current_row != -1: list.append("True" if x == columns else "False") current_row = i x = 0 # 判断当前元素是否在区间内 if df.iloc[i, j] >= min_val and df.iloc[i, j] <= max_val: x += 1 else: list2.append((i, j)) # 处理最后一行的结果 list.append("True" if x == columns else "False")
方式二:保留按行循环结构
保留原代码按行遍历的逻辑,仅用itertools处理列的遍历,更贴近原代码结构:
import itertools columns = len(df_test.columns) rows = len(df_test.index) list = [] list2 = [] def inRange(df, min_val, max_val): for i in range(rows): x = 0 # 用itertools遍历当前行的所有列 for j in itertools.product(range(columns)): j = j[0] # product返回元组,取第一个元素 if df.iloc[i, j] >= min_val and df.iloc[i, j] <= max_val: x += 1 else: list2.append((i, j)) list.append("True" if x == columns else "False")
补充说明
- 修正后的代码将参数名改为
min_val和max_val,避免与Python内置的min()、max()函数冲突,这是更规范的写法。 - 两种方式都能实现和原嵌套循环完全一致的逻辑,可根据个人习惯选择。
内容的提问来源于stack exchange,提问作者edit02
相关产品推荐
相关产品推荐

