我正在尝试绘制一些时间序列数据,其源时间是 UNIX 时间戳(自 1970 年以来的秒数),我想在 x 轴上的本地时区中查看日期/时间。我正在使用
DataFrame.plot
中的pandas
方法。无论我做什么,我似乎都在 x 轴上获得 UTC 时间。这适用于刻度标签及其位置。
这是一个演示脚本:
import time
from dateutil.tz import tzlocal
from pandas import DataFrame
from numpy import datetime64
from pandas import DatetimeIndex
from matplotlib.figure import Figure
figure = Figure(figsize=(7, 4))
figure.add_subplot()
ax = figure.axes[0]
now = time.time()
dt64s = [datetime64(int(when), 's') for when in (now - 3600, now - 1800, now)]
dti = DatetimeIndex(dt64s, tz=tzlocal())
data = {'a': [1, 2, 3], 'b': [4, 5, 6]}
df = DataFrame(data, index=dti) ## dt64s
df.plot(ax=ax)
figure.savefig('plot1.png')
这会在 UTC 中生成带有刻度线的图。如果我使用上面的普通
dt64s
,图像是相同的(我有点期待,因为它们实际上是 UNIXtimes,而 matplotlib 默认为 UTC)。然而,我对 DateLocator
之类的实验都没有帮助,或者根本没有做出任何改变。
***** 一夜好眠和更多实验
我取得了一些进步。这是一个更新的脚本:
import time
from dateutil.tz import tzlocal
from pandas import DataFrame
from numpy import datetime64
from pandas import DatetimeIndex
from matplotlib.dates import DateFormatter
from matplotlib.figure import Figure
figure = Figure(figsize=(7, 9))
figure.add_subplot()
ax = figure.axes[0]
now = time.time()
dt64s = [
datetime64(int(when), 's')
for when in (now + i * 1800 for i in range(-90, 1))
]
dti = DatetimeIndex(dt64s) ##, tz=tzlocal())
print(dti)
data = {
'a': [i for i, _ in enumerate(dt64s)],
'b': [i + 2 for i, _ in enumerate(dt64s)]
}
df = DataFrame(data, index=dti) ## dt64s
dfmt = DateFormatter("%Y-%m-%d %H:%M:%S %z %Z", tz=tzlocal())
ax.xaxis.set_major_formatter(dfmt)
ax.set_title(f"Data from {dti[0]}..{dti[-1]}")
df.plot(ax=ax)
figure.savefig('plot1.png')
还有一些更重要的变化:
DatetimeIndex
不再使用tz=
参数DateFormatter
以本地时间显示日期顺序:
更长的时间范围使区域效果更清晰,特别是日期和时间部分清晰,这有助于查看我当地的时钟进行比较。
tz=
的DatetimeIndex
参数与我想象的相反。我期望的是它将 datetime64
值作为 1970 UTC 的偏移量(即纯 UNIX 时间戳纪元)并生成本地化的 Pandas 日期时间对象 - 这些时间在本地时区中呈现为日历日期/时间。 However,它似乎做的是使用时区作为纪元的偏移量,并根据我当前的时区偏移量生成日期/时间skewed 即这意味着纪元参考是 1970 GMT+10(我的时区) ,有效地使时间戳提前 10 小时。
删除
tz=
参数可以消除这种偏差。我得到的 UTC 日期/时间对于我的输入时间戳是正确的。
DateFormatter
在索引中获取漂亮的 UTC 日期/时间,并在标记刻度线时 presents 在我当地的时区。部分胜利。
剩下的就是写一个本地时间感知的
Locator
。这个问题的激励图在 UTC 午夜有刻度线。我想将它们转移到我当地的午夜时区,因为我正在绘制太阳能输出并且这与我当地的阳光自然对齐。
为了得到正确的结果,我们需要:
导入 UNIX 时间戳:使用 pandas.to_datetime,指定单位('s')和时区('utc'),因为我们是“tzaware”
将数据帧转换为本地时间:使用 pandas.DatetimeIndex.tz_convert 和
tzlocal()
这将为您提供以下代码:
import time
from dateutil.tz import tzlocal
from pandas import DataFrame, DatetimeIndex, to_datetime
from matplotlib.figure import Figure
figure = Figure(figsize=(7, 4))
figure.add_subplot()
ax = figure.axes[0]
now = time.time()
utc_time = to_datetime([now - 3600, now - 1800, now], unit='s', utc=True)
dti = DatetimeIndex(utc_time).tz_convert(tz=tzlocal())
data = {'a': [1, 2, 3], 'b': [4, 5, 6]}
df = DataFrame(data, index=dti)
df.plot(ax=ax)
figure.savefig('plot1.png')
您可以使用
DateFormatter
来获得您想要的显示。