【问题标题】:Pandas maximize total value of a column based on another column total sum max熊猫根据另一列总和最大值最大化一列的总值
【发布时间】:2021-08-25 06:03:08
【问题描述】:

我有一个数据框:

id col1  col2
0  1000   250
1  2000   750
2  1500   350
3  3000   800
4  4500  2500
5  8500  4450
6  6300  1250

我试图找到可以最大化 col2 值总和的行,基于/给定这些行的总和 col1

最简单的方法是什么?

【问题讨论】:

  • 您要查找的关键字是背包问题
  • @Stef Knapsack 似乎内存很重,但是是的,它似乎确实是我正在寻找的东西。您会推荐任何具体的实现方式吗?
  • 是的,您可以使用动态编程方法,它提供pseudo-polynomial time 算法。这个想法是构建一个数组,其中单元格(w, i) 告诉您仅使用 ID 为 i 且权重最多为 w 的项目可以实现什么值。单元格(0, i)(w, 0) 易于填充;可以使用已填充的单元格用递归公式填充其他单元格。复杂度将与数组的单元数成正比,在您的示例中为 8*75,因为您只需要考虑权重的倍数 500。
  • 我不知道python中有一个已经实现的背包模块,尽管肯定存在几个。如果您不想自己实现它,可以在 google 中查找它们(尽管这是一个有趣的练习)。如果您要使用其他人的实现,我建议将col1 中的所有权重除以 500。

标签: python pandas math


【解决方案1】:

正如 cmets 中所建议的,这可能是背包问题,但我尝试根据您的要求实现我所理解的以下内容:

使用来自itertoolspowersetpd.concat

from itertools import chain, combinations

def powerset(iterable):
   """powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"""
   s = list(iterable)
   print(s)
   return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

df_groups = pd.concat([df.reindex(l).assign(grp=n) for n, l in 
                   enumerate(powerset(df.index))
                  if ((df.loc[list(l), 'col1'].sum() <= 1500))])

print(df_groups)

Output:

     id  col1   col2  grp
 0   0   1000   250   1
 2   2   1500   350   3

解释:

我们正在使用数据框的索引来使用powerset 函数创建行组。接下来,我们使用enumerate 来识别每个组,并使用assign 在数据框中创建一个新列,其中包含来自枚举的组号。 那么我们得到的是满足condition 的组,其中sum of col1.values &lt;= 15000 在那个特定的group 中。

参考:stackoverflow.com/questions/58119575

【讨论】:

  • 不错的蛮力答案,但您可能应该提到,如果数据集中有太多行(有多少行?),它会变得非常慢
  • 是的,这似乎有点慢。我的行数少于 3000 行。
  • @Stef 是的,它变得非常慢,但这是我想到的唯一想法!...也许它可以帮助 OP 获得一些见解。
猜你喜欢
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-21
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多