Pandas 找到行的子集,在其他列约束下最小化列的总和

2024-04-09

我有一个非常简单的想法,即找到行的子集,使一列的总和最小化,而另一列的总和必须大于某个值。

Example:

df = pd.DataFrame({'Names': ['a', 'b', 'c', 'd', 'e', 'f'],
               'Target': [35, 15, 12, 8, 7, 5],
               'Cost': [15, 40, 30, 30, 25, 10]})




    Names   Target  Cost
0   a       35      15
1   b       15      40
2   c       12      30
3   d       8       30
4   e       7       25
5   f       5       10

在上面的示例中,我希望找到使 Cost 列最小化的行子集,而 Target 之和必须大于 40。

在此示例中,我要构建的函数将返回 ['a', 'f'],因为满足约束 35 + 5 >= 40,并且成本 15 + 10 = 25 不能低于任何其他函数满足约束条件时的行组合。

我正在寻找哪些库或想法来解决这个问题?


我们可以将其设置为约束优化问题,它有四个部分:

  1. 创建变量:我们将用布尔向量表示我们对行选择的选择。第 k 个条目中的 True 意味着我们选择了第 k 行,而 False 则意味着我们没有选择。
  2. 指定约束:我们需要确保目标行的总和大于阈值。通过计算目标列和所选行向量之间的点积来完成。
  3. 指定目标函数。这里的目标函数是所选行的成本之和,即成本列与所选行向量的点积。
  4. 在这种情况下求解是最小化受约束的目标函数。

有几个 Python 运筹学库,即或图书馆 https://www.xiang.dev/python-or/用于解决此类问题。该解决方案使用Google OR 工具 https://developers.google.com/optimization这是一个“用于优化的开源软件套件”。

我们表明,使用优化包进行求解比对所有可能的行选择执行详尽搜索的替代解决方案要快得多。穷举搜索的计算复杂度呈指数级,O(2^nrows),因此仅适用于少量行(即

Code

import numpy as np 
import pandas as pd

# Google or-tools solver
from ortools.sat.python import cp_model

import timeit

def solve(df, threshold):
    '''
    Uses or-tools module to solve optimization

    '''
    weights = df['Target']
    cost = df['Cost']
    names = df['Names']

    # Creates the model.
    model = cp_model.CpModel()

    # Step 1: Create the variables
    # array containing row selection flags i.e. True if row k is selected, False otherwise
    # Note: treated as 1/0 in arithmeetic expressions
    row_selection = [model.NewBoolVar(f'{i}') for i in range(df.shape[0])]

    # Step 2: Define the constraints
    # The sum of the weights for the selected rows should be >= threshold
    model.Add(weights.dot(row_selection) >= threshold)

    # Step 3: Define the objective function
    # Minimize the total cost (based upon rows selected)
    model.Minimize(cost.dot(row_selection))

    # Step 4: Creates the solver and solve.
    solver = cp_model.CpSolver()
    solver.Solve(model)

    # Get the rows selected
    rows = [row for row in range(df.shape[0]) if solver.Value(row_selection[row])]

    return names[rows]


# Setup
df = pd.DataFrame({'Names': ['a', 'b', 'c', 'd', 'e', 'f'],
               'Target': [35, 15, 12, 8, 7, 5],
               'Cost': [15, 40, 30, 30, 25, 10]})

print(solve(df, 40))

# Output:
0    a
5    f
Name: Names, dtype: object

表现

当前解决方案(基于 OR-Tools)

%timeit main(df, 40)
3.13 ms ± 111 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

与穷举搜索算法相比,例如斯科特·波士顿解决方案 https://stackoverflow.com/questions/69473985/pandas-find-subset-of-rows-minimizing-the-sum-of-a-column-under-other-column-con/69474411#69474411.

from itertools import combinations, chain
    
df = pd.DataFrame(
        {
            "Names": ["a", "b", "c", "d", "e", "f"],
            "Target": [35, 15, 12, 8, 7, 5],
            "Cost": [15, 40, 30, 30, 25, 10],
        }
    )
    
    
def powerset(iterable):
        "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
        s = list(iterable)
        return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))
    
    
%timeit min( (df.loc[list(i)] for i in powerset(df.index) if df.loc[list(i), "Target"].sum() >= 40), key=lambda x: x["Cost"].sum(),)

64.4 ms ± 1.88 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

因此,使用 OR-Tools 比穷举搜索快约 20 倍(即 3.13 毫秒与 64.4 毫秒)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Pandas 找到行的子集,在其他列约束下最小化列的总和 的相关文章

  • LibreOffice 并行将 .docx 转换为 .pdf 效果不佳

    我有很多 docx 文件需要转换为 pdf 将它们一一转换需要很长时间 所以我编写了一个 python 脚本来并行转换它们 from subprocess import Popen import time import os os chdi
  • 将 yerr/xerr 绘制为阴影区域而不是误差线

    在 matplotlib 中 如何将误差绘制为阴影区域而不是误差条 例如 而不是 忽略示例图中各点之间的平滑插值 这需要进行一些手动插值 或者只是获得更高分辨率的数据 您可以使用pyplot fill between https matpl
  • 如何删除 PyCharm 中的项目?

    如果我关闭一个项目 然后删除该项目文件夹 则在 PyCharm 重新启动后 会再次创建一个空的项目文件夹 只需按顺序执行以下步骤即可 他们假设您当前在 PyCharm 窗口中打开了该项目 单击 文件 gt 关闭项目 关闭项目 在 PyCha
  • 尝试从网页Python和BeautifulSoup获取编码

    我试图从网页检索字符集 这会一直改变 目前我使用 beautifulSoup 来解析页面 然后从标题中提取字符集 这工作正常 直到我遇到一个网站 到目前为止 我的代码以及与其他页面一起使用的代码是 def get encoding soup
  • 是否有一个包可以维护所有带有符号的货币列表?

    是否有一个 python 包提供所有 或相当完整 货币的列表与符号 如美元的 有优秀的pycountry 贪财的 https github com limist py moneyed and ccy http code google com
  • python celery -A 的无效值无法加载应用程序

    我有一个以下项目目录 azima init py main py tasks py task py from main import app app task def add x y return x y app task def mul
  • 如何使用 opencv python 计算乐高积木上的孔数?

    我正在开发我的 python 项目 我需要计算每个乐高积木组件中有多少个孔 我将从输入 json 文件中获取有关需要计算哪个程序集的信息 如下所示 img 001 red 0 blue 2 white 1 grey 1 yellow 1 r
  • 如何在 Python 中的函数入口、内部和退出处进行日志记录

    我希望能够使用 Python 日志记录工具在我的代码中进行简单且一致的日志记录 我能够执行以下操作 我希望所有现有 未来的模块和函数都有 输入 和 完成 日志消息 我不想添加相同的代码片段来定义日志记录参数 如下所示don t want t
  • Python MySQL 操作错误:1045,“用户 root@'localhost' 的访问被拒绝

    我试图通过以下方式从我的 python 程序访问数据库 db mysql connect host localhost user Max passwd maxkim db TESTDB cursor db cursor 但是 我在第一行代码
  • 在 Mac OSX 上从 Python 3.6 运行 wine 命令

    我正在尝试用 Python 编写一个打开的脚本wine然后发送代码到wine终端打开一个 exe程序 这 exe程序也是命令驱动的 我可以打开wine 但我无法进一步 import shlex subprocess line usr bin
  • 在 Mac OS X 上安装 libxml2 时出现问题

    我正在尝试在我的 Mac 操作系统 10 6 4 上安装 libxml2 我实际上正在尝试在 Python 中运行 Scrapy 脚本 这需要我安装 Twisted Zope 现在还需要安装 libxml2 我已经下载了最新版本 2 7 7
  • NumPy 相当于 Keras 函数 utils.to_categorical

    我有一个使用 Keras 进行机器学习的 Python 脚本 我正在构建 X 和 Y 它们分别是特征和标签 标签的构建方式如下 def main depth 10 nclass 101 skip True output True video
  • App Engine 实体到字典

    将 google app engine 实体 在 python 中 复制到字典对象的好方法是什么 我正在使用 db Expando 对象 所有属性均为扩展属性 Thanks 有一个名为foo尝试 foo dict
  • 使用seaborn绘制简单线图

    我正在尝试使用seaborn python 绘制ROC曲线 对于 matplotlib 我只需使用该函数plot plt plot one minus specificity sensitivity bs where one minus s
  • 为正则表达式编写解析器

    即使经过多年的编程 我很羞愧地说我从未真正完全掌握正则表达式 一般来说 当问题需要正则表达式时 我通常可以 在一堆引用语法之后 想出一个合适的正则表达式 但我发现自己越来越频繁地使用这种技术 所以 自学并理解正则表达式properly 我决
  • 将字符串中的随机字符转换为大写

    我尝试随机附加文本字符串 这样就不只是有像这样的输出 gt gt gt david 我最终会得到类似的东西 gt gt gt DaViD gt gt gt dAviD 我现在的代码是这样的 import random import stri
  • 确定分割形状几何体的“左”侧和“右”侧

    我的问题是 我怎样才能确定哪一个Aside and Bside的侧面已经分割的旋转矩形几何体 http nbviewer jupyter org urls dl dropbox com s ll3mchnx0jwzjnf determine
  • numpy polyfit 中使用的权重值是多少以及拟合误差是多少

    我正在尝试对 numpy 中的某些数据进行线性拟合 Ex 其中 w 是该值的样本数 即对于点 x 0 y 0 我只有 1 个测量值 该测量值是2 2 但对于这一点 1 1 我有 2 个测量值 值为3 5 x np array 0 1 2 3
  • PyQt5:如何使QThread返回数据到主线程

    I am a PyQt 5 4 1 1初学者 我的Python是3 4 3 这是我尝试遵循的many https mayaposch wordpress com 2011 11 01 how to really truly use qthr
  • 将时间添加到日期时间

    我有一个像这样的日期字符串 然后使用strptime 所以就像这样 my time datetime datetime strptime 07 05 15 m d Y 现在我想添加 23 小时 59 分钟my time 我努力了 timed

随机推荐