Pandas DataFrame条件匹配与新列生成报错问题求助
问题解决:Pandas中检查后续行满足条件并新增列
原始DataFrame
High Close Close Time 2022-10-23 21:41:59.999 19466.02 19461.29 2022-10-23 21:42:59.999 19462.48 19457.83 2022-10-23 21:43:59.999 19463.13 19460.09 2022-10-23 21:44:59.999 19465.15 19463.76
需求说明
- 对每一行,检查其之后最多600行内是否存在某一行同时满足:
- 该行的Close值 > 当前行的Close值
- 该行的High值 < 当前行的High值
- 满足条件时,新增
LC、HC、HH、LH列记录对应值:LC:当前行的Close值(仅当前行填充)HC:目标行的Close值(仅目标行填充)HH:当前行的High值(仅当前行填充)LH:目标行的High值(仅目标行填充)
预期输出
High Close LC HC HH LH Close Time 2022-10-23 21:41:59.999 19466.02 19461.29 19461.29 NaN 19466.02 NaN 2022-10-23 21:42:59.999 19462.48 19457.83 NaN NaN NaN NaN 2022-10-23 21:43:59.999 19463.13 19460.09 NaN NaN NaN NaN 2022-10-23 21:44:59.999 19465.15 19463.76 NaN 19463.76 NaN 19465.15
尝试的代码及报错
第一次尝试代码
# Checking if conditions are met for i in range(len(df)): for a in range(i,600): if (df.iloc[i:, 1] < df.iloc[a, 1]) & (df.iloc[i:, 0] > df.iloc[a, 0]): # Creating new DataFrame columns df['LC'] = df.iloc[i, 1] df['HC'] = df.get_loc[i,1] df['HH'] = df.get_loc[a, 0] df['LH'] = df.get_loc[a, 0] else: continue
报错信息
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
问题分析
df.iloc[i:, 1]返回的是从第i行开始的Series,和单个值df.iloc[a,1]比较后得到布尔Series,直接放在if条件里会触发歧义报错——Pandas无法判断你要的是"全满足"还是"任一满足"。df.get_loc()是用来获取列名对应的索引位置的,不能用来取单元格值,这里用法完全错误,应该用df.iloc直接取值。
第二次尝试代码
idx_close, idx_high = map(df.columns.get_loc, ["Close", "High"]) # Check Conditions for i in range(len(df)): bool_l = [((df.iloc[i, idx_close] < df.iloc[a, idx_close]) & (df.iloc[i, idx_high] > df.iloc[a, idx_high]) ).any() for a in range(i, 600)] # Creating new DataFrame columns df.loc[i, 'LC'] = df.iloc[i,1] df.loc[bool_l, 'HC'] = df.iloc[bool_l, 1] # Creating new DataFrame columns df.loc[i, 'HH'] = df.iloc[i, 0] df.loc[bool_l, 'LH'] = df.iloc[bool_l, 0]
报错信息
IndexError: Boolean index has wrong length: 600 instead of 2867
问题分析
bool_l是长度为600的布尔列表,但你的DataFrame有2867行,用短列表去索引长DataFrame的行,必然长度不匹配报错。range(i,600)写法错误:当i大于600时这个范围是空的,而且应该取i+1到min(i+600, len(df)),确保只检查当前行之后的最多600行,且不超出DataFrame范围。
解决方案
下面是修正后的代码,解决了上述所有问题:
import pandas as pd # 先初始化新增的4列为缺失值 df[['LC', 'HC', 'HH', 'LH']] = pd.NA # 获取列对应的索引位置 idx_close = df.columns.get_loc('Close') idx_high = df.columns.get_loc('High') idx_lc = df.columns.get_loc('LC') idx_hc = df.columns.get_loc('HC') idx_hh = df.columns.get_loc('HH') idx_lh = df.columns.get_loc('LH') total_rows = len(df) for i in range(total_rows): # 确定后续检查的结束索引:最多查当前行之后600行,不超过总行数 end_idx = min(i + 601, total_rows) # 遍历当前行之后的行(从i+1开始) for a in range(i+1, end_idx): # 单个行的条件判断,不会产生布尔Series if (df.iloc[a, idx_close] > df.iloc[i, idx_close]) and (df.iloc[a, idx_high] < df.iloc[i, idx_high]): # 填充当前行的LC和HH df.iloc[i, idx_lc] = df.iloc[i, idx_close] df.iloc[i, idx_hh] = df.iloc[i, idx_high] # 填充目标行的HC和LH df.iloc[a, idx_hc] = df.iloc[a, idx_close] df.iloc[a, idx_lh] = df.iloc[a, idx_high] # 如果只需要找第一个满足条件的行,就加break;要找所有满足的就去掉 break
代码说明
- 提前初始化新增列,避免后续赋值时出现"列不存在"的错误。
- 计算
end_idx确保检查范围不超出DataFrame,同时严格限制在当前行之后最多600行。 - 用单个值做条件判断,避免布尔Series导致的歧义报错。
- 直接通过列索引定位赋值,确保操作准确高效。
内容的提问来源于stack exchange,提问作者Callum
相关产品推荐
相关产品推荐

