【问题标题】:Python, improving for loop performancePython,提高 for 循环性能
【发布时间】:2018-11-08 04:57:24
【问题描述】:

我创建了一个名为 localSun 的类。我采用了地球-太阳系统的简化模型,并试图计算地球上任何时间任何位置的太阳高度角。当我运行当前时间的代码并检查 timeandddate 时,它​​匹配得很好。所以它起作用了。

但后来我想基本上经历一年并将所有高度角存储到一个特定位置的数组(numpy 数组)中,我每隔 1 分钟进行一次。

这是我第一次天真的尝试,我相当肯定这对性能没有好处。反正我只是想测试一下性能。

import numpy as np
from datetime import datetime
from datetime import date
from datetime import timedelta
...

...  
altitudes = np.zeros(int(year/60))

m = datetime(2018, 5, 29, 15, 21, 0)
for i in range(0, len(altitudes)):
    n = m + timedelta(minutes = i+1)
    nn = localSun(30, 0, n)

    altitudes[i] = nn.altitude() # .altitude() is a method in localSun

altitudes 是我要存储所有高度的数组,它的大小是 525969,基本上是一年中的分钟数。

localSun() 对象采用 3 个参数:colatitude (30 度)、经度 (0 度) 和一个日期时间对象,该对象具有一个多小时前的时间(发布时)

所以问题是:以 1 分钟为间隔度过一年并计算当时的高度角是一种有效的方法,因为这看起来相当缓慢。我应该使用 map 来更新高度角的值而不是 for 循环。我想我每次都必须创建一个新的 localSun 对象。此外,一直创建这些变量 n 和 nn 可能很糟糕。

我们可以假设 localSun 对象的所有方法都可以正常工作。我只是在问什么是一种有效的方法(如果有的话)以 1 分钟的间隔经历一年并用高度更新数组。我拥有的代码应该能提供足够的信息。

我什至想在 1 秒间隔后执行此操作,因此很高兴知道是否有有效的方法。我试过了,但如果我使用这段代码,它需要很长时间。

在大学计算机上完成这段代码大约需要一分钟,据我所知,这速度相当快。

如果有人可以回答,非常感谢。提前致谢!

【问题讨论】:

  • 如果这是工作代码,请考虑将其发布到Code Review。那边的小伙伴会很乐意改进它
  • 既然您已经在使用 numpy,那么如何将日期存储在 numpy 数组中以便可以对循环进行矢量化?
  • 我会考虑用 len(altitudes) 制作一个常量/变量,这会在迭代过程中略微提高性能。虽然,为什么不for i, j in enumerate(altitudes) 会给你索引和高度值。
  • Numpy 可以直接与datetimes and timedeltas 一起工作,所以基本上取决于localSun 是否可以接受并返回一个日期时间数组,而不仅仅是一个值。
  • 我认为这在很大程度上取决于SolarSun 的实际作用。如果您可以使其与日期时间数组一起使用,则可以对 for 循环进行矢量化。仅凭您共享的代码很难说更多

标签: python performance dictionary for-loop


【解决方案1】:

由于您已经在使用numpy,您可以使用pandas 更进一步。它具有强大的日期和时间操作例程,例如pd.date_range

import pandas as pd


start = pd.Timestamp(year=2018, month=1, day=1)
stop = pd.Timestamp(year=2018, month=12, day=31)
dates = pd.date_range(start, stop, freq='min')
altitudes = localSun(30, 0, dates)

然后您需要调整您的 localSun 以使用 pd.Timestamp 数组而不是单个 datetime.datetime

从分钟更改为秒就像将 freq='min' 更改为 freq='S' 一样简单。

【讨论】:

  • 你不需要一个完整的另一个库。 numpy 处理日期范围就好了。在我们进一步了解 localSun 之前,您的回答并没有真正增加任何有用的东西。
【解决方案2】:

Numpy 有幼稚的 datetimetimedelta support 所以你可以采取这样的方法:

start = datetime.datetime(2018,5,29,15,21,0)
end = datetime.datetime(2019,5,29,15,21,0)
n = np.arange(start, end, dtype='datetime64[m]') # [m] specifies the interval as minutes
altitudes = np.vectorize(lambda x, y, z: localSun(x, y, z).altitude())(30,0,n)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 2019-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    相关资源
    最近更新 更多