【问题标题】:how to get ticks every hour?如何每小时获得滴答声?
【发布时间】:2018-07-25 05:08:56
【问题描述】:

考虑这个简单的例子

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
import matplotlib.dates as mdates

pd.__version__
Out[147]: u'0.22.0'

idx = pd.date_range('2017-01-01 05:03', '2017-01-01 18:03', freq = 'min')

df = pd.Series(np.random.randn(len(idx)),  index = idx)
df.head()
Out[145]: 
2017-01-01 05:03:00   0.4361
2017-01-01 05:04:00   0.9737
2017-01-01 05:05:00   0.8430
2017-01-01 05:06:00   0.4292
2017-01-01 05:07:00   0.5739
Freq: T, dtype: float64

我想绘制这个,并且每小时都有刻度。我用:

fig, ax = plt.subplots()
hours = mdates.HourLocator(interval = 1)  #
h_fmt = mdates.DateFormatter('%H:%M:%S')

df.plot(ax = ax, color = 'black', linewidth = 0.4)

ax.xaxis.set_major_locator(hours)
ax.xaxis.set_major_formatter(h_fmt)

给了

为什么这里的刻度不是每小时都出现一次?感谢您的帮助!

【问题讨论】:

  • 你应该和xtick一起玩。
  • 你知道怎么做吗?谢谢!!
  • @ℕʘʘḆḽḘ:所以你想要的输出只是看到每一个完整小时的峰值?
  • @Skandix,是的,我不仅想在 8 点、10 点、12 点看到滴答声,还想在每小时 6、7、8、9、10 点等看到滴答声

标签: python pandas matplotlib


【解决方案1】:

问题在于,虽然 pandas 通常直接包装 matplotlib 绘图方法,但对于带有日期的绘图,情况并非如此。一旦涉及日期,pandas 就使用完全不同的日期数字表示,因此也使用自己的定位器来表示刻度。

如果您想在使用 pandas 创建的绘图上使用 matplotlib.dates 格式化程序或定位器,您可以在 pandas 绘图中使用 x_compat=True 选项。

df.plot(ax = ax, color = 'black', linewidth = 0.4, x_compat=True)

这允许使用matplotlib.dates 格式化程序或定位器,如下所示。 否则,您可以将df.plot(ax = ax, color = 'black', linewidth = 0.4) 替换为

ax.plot(df.index, df.values, color = 'black', linewidth = 0.4)

完整示例:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

idx = pd.date_range('2017-01-01 05:03', '2017-01-01 18:03', freq = 'min')
df = pd.Series(np.random.randn(len(idx)),  index = idx)

fig, ax = plt.subplots()
hours = mdates.HourLocator(interval = 1)
h_fmt = mdates.DateFormatter('%H:%M:%S')

ax.plot(df.index, df.values, color = 'black', linewidth = 0.4)
#or use
df.plot(ax = ax, color = 'black', linewidth = 0.4, x_compat=True)
#Then tick and format with matplotlib:
ax.xaxis.set_major_locator(hours)
ax.xaxis.set_major_formatter(h_fmt)

fig.autofmt_xdate()
plt.show()


如果此处使用 pandas 的动机是(如下面的 cmets 所述)能够使用 secondary_y,则 matplotlib 绘图的等价物将是双轴 twinx
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

idx = pd.date_range('2017-01-01 05:03', '2017-01-01 18:03', freq = 'min')

df = pd.DataFrame(np.cumsum(np.random.randn(len(idx), 2),0), 
                  index = idx, columns=list("AB"))

fig, ax = plt.subplots()
ax.plot(df.index, df["A"], color = 'black')
ax2 = ax.twinx()
ax2.plot(df.index, df["B"], color = 'indigo')

hours = mdates.HourLocator(interval = 1)
h_fmt = mdates.DateFormatter('%H:%M:%S')
ax.xaxis.set_major_locator(hours)
ax.xaxis.set_major_formatter(h_fmt)

fig.autofmt_xdate()
plt.show()

【讨论】:

  • 谢谢。也许让 Pandas 进行绘图的解决方法是获取常规时间戳索引而不是 pandas 日期时间?
  • 我想保留 Pandas 构造函数,因为我广泛使用 plot 的 secondary_y 参数来显示多个时间序列...
  • 我想不出任何解决方法。 matplotlib.dates 假定数字轴表示自 0001-01-01 UTC 以来的天数,加 1。只有当轴使用此日期时间格式时,它才会正确地标记和标记轴。另一方面,pandas 将根据数据创建其轴单位,并为这些单位使用适当的定位器。我能想到的唯一选择是操纵正在使用的熊猫格式化程序。不过,我不知道有任何连贯的方式来做到这一点。
  • matplotlib 中的 secondary_y 的等价物是创建一个 twinx 并将第二个绘图绘制到该轴上。与一个相比,这通常会导致 3 个代码行,所以还不错。
  • 不确定是什么问题。这里最简单的是fig.autofmt_xdate(rotation=90)
【解决方案2】:

仅使用 pandas 的解决方案

您可以使用DatetimeIndex 的时间戳设置每小时的刻度。可以利用时间戳的datetime properties 创建刻度。

import numpy as np   # v 1.19.2
import pandas as pd  # v 1.1.3

idx = pd.date_range('2017-01-01 05:03', '2017-01-01 18:03', freq='min')
series = pd.Series(np.random.randn(len(idx)), index=idx)

ax = series.plot(color='black', linewidth=0.4, figsize=(10,4))
ticks = series.index[series.index.minute == 0]
ax.set_xticks(ticks)
ax.set_xticklabels(ticks.strftime('%H:%M'));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    相关资源
    最近更新 更多