使用带有大表的循环的 python 性能问题

Posted

技术标签:

【中文标题】使用带有大表的循环的 python 性能问题【英文标题】:python performance problems using loops with big tables 【发布时间】:2017-12-16 21:34:56 【问题描述】:

我正在使用 python 和多个库(如 pandas 和 scipy)来准备数据,以便开始更深入的分析。例如,出于准备目的,我创建了两个日期不同的新列。 我的代码提供了预期的结果,但速度很慢,所以我不能将它用于具有 80K 行的表。运行时间大约需要。 80分钟的桌子就为了这个简单的操作。

这个问题肯定和我的写作操作有关:

tableContent[6]['p_test_Duration'].iloc[x] = difference

此外,python 提供了一个警告:

日期差的完整代码示例:

import time
from datetime import date, datetime

tableContent[6]['p_test_Duration'] = 0

#for x in range (0,len(tableContent[6]['p_test_Duration'])):
for x in range (0,1000):
    p_test_ZEIT_ANFANG = datetime.strptime(tableContent[6]['p_test_ZEIT_ANFANG'].iloc[x], '%Y-%m-%d %H:%M:%S')
    p_test_ZEIT_ENDE = datetime.strptime(tableContent[6]['p_test_ZEIT_ENDE'].iloc[x], '%Y-%m-%d %H:%M:%S')
    difference = p_test_ZEIT_ENDE - p_test_ZEIT_ANFANG

    tableContent[6]['p_test_Duration'].iloc[x] = difference

正确的结果表:

【问题讨论】:

如果你使用 pandas,为什么不使用 pandas datetime 呢?如果您可以添加示例输入,那么帮助会更容易 【参考方案1】:

去掉循环,将函数应用到整个系列。

ZEIT_ANFANG = tableContent[6]['p_test_ZEIT_ANFANG'].apply(lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S'))
ZEIT_ENDE = tableContent[6]['p_test_ZEIT_ENDE'].apply(lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M:%S'))
tableContent[6]['p_test_Duration'] = ZEIT_ENDE - ZEIT_ANFANG

【讨论】:

非常感谢。它工作完美!对您的代码只有一条评论:缺少两个括号来关闭 .apply() 方法。 很高兴它起作用了,添加了缺少的括号,我不知道人们如何使用 lisp 括号进行管理;-)【参考方案2】:

您可以使用pd.to_datetime 对日期的转换进行矢量化处理,避免不必要地使用apply

tableContent[6]['p_test_Duration'] = (
    pd.to_datetime(tableContent[6]['p_test_ZEIT_ENDE']) -
    pd.to_datetime(tableContent[6]['p_test_ZEIT_ANFANG'])
)

此外,由于链式索引分配,您收到了 SettingWithCopy 警告

tableContent[6]['p_test_Duration'].iloc[x] = difference

如果你按照我建议的方式去做,你就不必担心了。

【讨论】:

这个答案比较好~为了提高效率不应该考虑apply【参考方案3】:

其他答案都很好,但我建议您通常避免使用链式索引。 pandas 文档explicitly discourage chained indexing 因为它要么产生不可靠的结果,要么速度很慢(由于多次调用 __getitem__)。假设您的数据框是多索引的,您可以替换:

tableContent[6]['p_test_Duration'].iloc[x] = difference

与:

tableContent.loc[x, (6, 'p_test_Duration')] = difference

你有时可以绕过这个问题,但为什么不学习最不可能在未来引起问题的方法呢?

【讨论】:

以上是关于使用带有大表的循环的 python 性能问题的主要内容,如果未能解决你的问题,请参考以下文章

大表的mysql性能问题

多对多关系 - 大表的查询性能

MySQL:连接小到大表的性能不佳

删除查询中包含大表的 IN 子句中的子查询性能

将 MySQL 索引添加到大表的性能影响

MySQL大表性能优化