在 Python 中使用 ephem 从日期时间索引计算日出和日落时间

calculate sunrise and sunset times from a datetime index using ephem in Python

我有一个包含 DateTime 索引的每日时间序列。我想计算 DataFrame 中每一天的日出和日落时间。结果将显示在 riseset 列中。下面是我使用 pyephem 的脚本:

import ephem
import datetime

AliceS = ephem.Observer()
AliceS.lat = '-23.762'
AliceS.lon = '133.875'

AliceS.date = df.index

sun = ephem.Sun()

df['rise'] = ephem.localtime(AliceS.next_rising(sun))
df['set'] = ephem.localtime(AliceS.next_setting(sun))

这加注

ValueError: dates must be initialized from a number, string, tuple, or datetime

我认为错误的原因是 AliceS.date = df.index,但我不知道如何解决。

以下是日期时间索引的示例:

DateTime
2016-04-02
2016-04-03
2016-04-04
2016-04-07
2016-04-08

来自 docs 的首页:

PyEphem does not interoperate with NumPy and so is awkward to use in a modern IPython Notebook.

这基本上意味着 next_rising and next_setting 方法只能对标量进行操作。快速而肮脏的解决方案是编写一个循环将索引的每个元素转换为兼容格式并以这种方式计算值:

import ephem
import datetime

AliceS = ephem.Observer()
AliceS.lat = '-23.762'
AliceS.lon = '133.875'

sun = ephem.Sun()

def get_time(obs, obj, func):
    func = getattr(obs, func)
    def inner(date)
        obs.date = date
        return ephem.localtime(func(obj))
    return inner

df['rise'] = pd.Series(df.index).apply(get_time(AliceS, sun, 'next_rising'))
df['set'] = pd.Series(df.index).apply(get_time(AliceS, sun, 'next_setting'))

不要让紧凑的(-ish)符号欺骗你,apply 仍然只是一个 for 循环。

更好的解决方案是遵循 docs:

中的建议

I recommend using Skyfield instead of PyEphem if it’s possible for your new project to do so! (The only thing missing at this point is predicting positions from Kelperian orbital elements for comets and asteroids.)

这里是link到Skyfield. It is available via normal channels such as pypi and GitHub