【发布时间】:2021-05-25 23:15:41
【问题描述】:
我是 Python 新手,已经习惯了这些非常方便的隐式数组/列表操作,所以请多多包涵。我已经完成了一个概念验证代码(120 种组合),但正如预期的那样,在处理完整数据集(400 万种组合)时,它的速度明显放缓。当前的减速在以下for循环中:
for i in Combinations:
PropList = function.CalculateTotalPoints(ItemDict, i)
CombinationSets.loc[Combinations.index(i), 'Density':] = PropList
我试图不让这成为一堵文字墙,而是提供足够的信息来理解目标。
- 组合 - 这是一个包含 4 个项目(400 万行)的所有唯一组合的数据框。当不再需要它时,我最终会在循环后删除它
- PropList - 这是特定行中 4 项的累积属性的返回列表
- ItemDict - 这是一个数据框,包含各个项目的所有属性值
- CombinationSets - 这是“最终”数据框,其中包含来自 Combinations 的 4 个唯一项目以及来自 CalculatedTotalPoints 函数的附加 PropList。
- CalculateTotalPoints - 此函数接受 4 个项目 (i) 的列表以及对具有所有属性值 (ItemDict) 的数据框的引用。它实际上只是在执行一些简单的加法和除法运算,并添加一些逻辑并返回各种累积属性的列表。
我确信这里发生了很多“不是很棒的 Python”的事情,但我目前的想法是:
- Python 可能有更好/更快的方法来实现这个循环,而不是指定一个 for 循环(列表理解?)
- ItemDict 不是特别大,但可能每次都传递给函数是不必要的开销
- 由于 CombinationSet 数据帧的每一行都是相互独立的,我应该尝试实现多处理,以便可以处理多行
编辑 1: 我无法弄清楚如何隔离代码足以产生一个小示例问题。不适合后期长寿,但我已将主要代码添加到 for 循环、支持函数和示例数据到 Github Gist(已删除)
编辑 2: 从我在别处读到的内容看来,for 循环通常不是 Python 中循环的首选方法。我还没有成功地矢量化我的函数。但是,我确实研究了这个 for 循环的时间、函数(内部有一个 for 循环)和 PropList 的分配。在运行小型(120 种组合)或大型(450 万)组时,for 循环和函数具有相似(相当快)的性能。在这两种情况下,下面的行都是最长的。对于大型数据集,大约需要 1 秒。
CombinationSets.loc[Combinations.index(i), 'Density':] = PropList
编辑 3:
我能够减少循环操作的时间,而不是在循环内执行合并操作CombinationSets.loc[ ...,而是列出了返回的PropList。退出 for 循环后,我立即执行了合并操作。由于它目前设置为通过 for 循环的单次运行是 ~0.004 秒对 1 秒。可能还可以进行其他优化,但我会将其保存到单独的帖子中。
【问题讨论】:
-
你。需要显示一些可以使用的数据
-
请提供预期的minimal, reproducible example (MRE)。我们应该能够复制和粘贴您的代码的连续块,执行该文件,并重现您的问题以及跟踪问题点的输出。这让我们可以根据您的测试数据和所需的输出来测试我们的建议。您发布的代码缺少必要的符号定义。 看起来您正在使用 PANDAS,在这种情况下,您将丢弃整个数据帧上可用的矢量化操作。
-
请include a minimal data frame 作为您的 MRE 的一部分。
-
我希望有一个更通用的答案,并避免只发布一堆代码来涉水,但似乎答案可能更细微,需要更多细节。当我在学习 Python 时,代码不容易“分块”,所以我想看看如何最好地做到这一点。谢谢。
标签: python python-multiprocessing