Python DataFrame列优化:生成满足约束条件的第三列方案咨询
生成满足区间与总和约束的DataFrame列解决方案
核心逻辑
首先必须确认目标总和落在所有行min值的总和与所有行max值的总和之间,否则无解。若可行,优先给每行分配基准值(比如min值),再将剩余需要补足的量按每行的可分配空间(max-min)均匀分摊;如果需要更严谨的“均匀”(比如最小化各值与理论均值的偏差),可以用线性规划求解。
推荐库
pandas:处理DataFrame的基础工具,必备scipy.optimize:用于线性规划求解,适合需要严谨约束的场景cvxpy(可选):如果涉及二次优化(比如最小化方差),这个库更易用
实现示例
方法1:贪心均匀分配(简单高效,适合大多数场景)
import pandas as pd # 示例数据 df = pd.DataFrame({ 'min number': [1, 2, 3, 4], 'max number': [5, 6, 7, 8] }) target_sum = 18 # 校验目标总和是否在可行范围内 min_total = df['min number'].sum() max_total = df['max number'].sum() if not min_total <= target_sum <= max_total: raise ValueError(f"目标总和必须处于 [{min_total}, {max_total}] 区间内") # 初始分配最小值,计算剩余待分配量 df['result'] = df['min number'] remaining = target_sum - min_total # 计算每行可额外分配的空间 df['available_space'] = df['max number'] - df['min number'] # 循环均匀分配剩余量 while remaining > 1e-9: # 处理浮点精度问题 # 计算当前剩余量的平均分配值 avg_add = remaining / len(df) # 给每行分配不超过其可用空间的量 add_amount = df['available_space'].clip(upper=avg_add) # 更新结果、剩余量和可用空间 df['result'] += add_amount remaining -= add_amount.sum() df['available_space'] -= add_amount # 过滤掉已无分配空间的行 df = df[df['available_space'] > 1e-9].copy() # 可选:保留两位小数 df['result'] = df['result'].round(2)
方法2:线性规划求解(严谨优化,最小化偏差)
如果需要让生成的列尽可能接近理论均值(target_sum/行数),可以用线性规划最小化各值与均值的偏差:
from scipy.optimize import linprog import pandas as pd df = pd.DataFrame({ 'min number': [1, 2, 3, 4], 'max number': [5, 6, 7, 8] }) target_sum = 18 n_rows = len(df) target_avg = target_sum / n_rows # 目标函数:最小化各值与均值的绝对偏差之和(转化为线性约束) # 引入辅助变量s_i = |x_i - target_avg|,目标是sum(s_i)最小 c = [0]*n_rows + [1]*n_rows # x_i的系数为0,s_i的系数为1 # 约束条件: # 1. sum(x_i) = target_sum A_eq = [[1]*n_rows + [0]*n_rows] b_eq = [target_sum] # 2. x_i - target_avg <= s_i → x_i - s_i <= target_avg # 3. target_avg - x_i <= s_i → -x_i - s_i <= -target_avg A_ub = [] b_ub = [] for i in range(n_rows): row1 = [0]*n_rows + [0]*n_rows row1[i] = 1 row1[n_rows + i] = -1 A_ub.append(row1) b_ub.append(target_avg) row2 = [0]*n_rows + [0]*n_rows row2[i] = -1 row2[n_rows + i] = -1 A_ub.append(row2) b_ub.append(-target_avg) # 变量边界:min_i <= x_i <= max_i;s_i >= 0 bounds = [] for min_val, max_val in zip(df['min number'], df['max number']): bounds.append((min_val, max_val)) for _ in range(n_rows): bounds.append((0, None)) # 求解线性规划 res = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=bounds, method='highs') if res.success: df['result'] = res.x[:n_rows].round(2) else: raise ValueError("无法找到满足所有约束的解")
学习资料推荐
- YouTube视频系列:
- Python Data Science Tutorials:涵盖pandas核心操作与数据处理技巧,帮你快速掌握DataFrame的各类操作
- Optimization with Python:系统讲解Python中的优化工具(包括scipy、cvxpy),从基础线性规划到复杂优化问题都有实操案例
- Advanced Pandas Tutorials:深入讲解pandas的高级功能,适合处理这类带约束的数据列生成场景
内容的提问来源于stack exchange,提问作者Tobias Funke
相关产品推荐
相关产品推荐

