如何为DataFrame每行依次以各列为目标值获取符合条件的最大值
问题分析与解决方案
首先看你代码里的核心问题:
逻辑错误:你在循环每一列时,只要遇到一个不小于
date1的值,就直接把max设为date1,这会覆盖之前找到的符合条件的最大值。比如AA行的所有其他日期都小于date1,理论上不会触发else分支,但如果你的日期是字符串类型而非datetime,可能会出现比较逻辑错误;另外,你初始max设为2011-1-1,如果日期是字符串格式,和datetime对象比较会直接报错。语法问题:
if row[i] < row['date1']后面缺少冒号,这会导致代码无法正常运行,可能你实际运行时修改了但没写出来?
修正步骤
第一步:确保日期列是datetime类型
字符串格式的日期比较会有bug(比如'2019-10-1'作为字符串会比'2019-2-3'小,因为第一个不同字符是1 vs 2),所以先统一转换类型:
df[['date1','date2','date3','date4','date5','date6']] = df[['date1','date2','date3','date4','date5','date6']].apply(pd.to_datetime)
第二步:修正单个target(date1)的代码
我们需要先收集所有小于目标值的日期,再取最大值;如果没有符合条件的日期(即目标值是该行最小值),才返回目标值本身:
date1temp = [] for index, row in df.iterrows(): target = row['date1'] # 获取除date1外的所有日期列 other_dates = row[['date2','date3','date4','date5','date6']] # 筛选小于target的日期 smaller_dates = other_dates[other_dates < target] if not smaller_dates.empty: max_val = smaller_dates.max() else: max_val = target date1temp.append((index, max_val, target)) cols = ['index','max','target'] result = pd.DataFrame(date1temp, columns=cols)
运行这段代码就能得到你期望的输出:
index max target 0 AA 2019-05-21 2019-08-01 1 BB 2019-03-12 2019-03-12 2 CC 2019-01-07 2019-01-11
第三步:扩展到所有date1-date6列
如果需要处理所有6个日期列作为target的情况,不用重复写代码,可以封装成函数并应用到每行:
def get_max_less_than_target(row): result_rows = [] date_columns = ['date1','date2','date3','date4','date5','date6'] for target_col in date_columns: target_val = row[target_col] # 获取当前target列之外的所有日期列 other_cols = [col for col in date_columns if col != target_col] other_vals = row[other_cols] # 筛选小于目标值的项 filtered = other_vals[other_vals < target_val] if not filtered.empty: max_less = filtered.max() else: max_less = target_val result_rows.append({ 'index': row.name, 'target_column': target_col, 'target_value': target_val, 'max_less_than_target': max_less }) return pd.DataFrame(result_rows) # 应用到每行并合并结果 final_output = df.apply(get_max_less_than_target, axis=1).concat()
这样就能一次性得到所有列作为target的结果啦。
内容的提问来源于stack exchange,提问作者Annie
相关产品推荐
相关产品推荐

