How to change the datetime tick label frequency for matplotlib plots?
下面显示的是模拟数据图,其中包含我要修改的xtick。默认情况下,pd.df.plot选择大约间隔3个月的日期作为刻度。但是我想要的是每个月都在变动。做这个的最好方式是什么?那季节tick呢?先感谢您。
首先,您必须将pandas日期对象转换为python日期对象。由于matplotlib内部日期转换功能,因此需要进行此转换。然后使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import pandas as pd import numpy as np import matplotlib.pylab as plt import matplotlib.dates as mdates # convert date objects from pandas format to python datetime index = pd.date_range(start ="2015-07-01", end ="2017-01-01", freq ="D") index = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in index] data = np.random.randint(1,100, size=len(index)) df = pd.DataFrame(data=data,index=index, columns=['data']) print (df.head()) ax = df.plot() # set monthly locator ax.xaxis.set_major_locator(mdates.MonthLocator(interval=1)) # set formatter ax.xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y')) # set font and rotation for date tick labels plt.gcf().autofmt_xdate() plt.show() |
对于季节标签,您必须自己构造它,然后使用
df的头:
1 2 3 4 5 6 | data 2015-07-01 26 2015-07-02 33 2015-07-03 46 2015-07-04 69 2015-07-05 17 |
我很难获得@Serenity答案,因为我直接与Matplotlib合作,而不是绘制Pandas数据集。因此,如果您是其中之一,我的回答可能会有所帮助。
用Matplotlib.plot()绘图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import pandas as pd import matplotlib.pyplot as plt import matplotlib.dates as mdates # Process dataset bitcoin['Date'] = pd.to_datetime(bitcoin['Date']) bitcoin['Open'] = pd.to_numeric(bitcoin['Open']) # Plot plt.figure() plt.plot(bitcoin['Date'], bitcoin['Open']) ax = plt.gca() ax.xaxis.set_major_locator(mdates.MonthLocator(interval=4)) ax.xaxis.set_major_formatter(mdates.DateFormatter('%d-%m-%Y')) plt.gcf().autofmt_xdate() # Rotation plt.show() |
1 2 3 4 5 6 7 8 | bitcoin[['Date', 'Open']].head() Date Open 0 2017-09-05 4228.29 1 2017-09-04 4591.63 2 2017-09-03 4585.27 3 2017-09-02 4901.42 4 2017-09-01 4701.76 |
此答案基于Serenity的答案以及ImportanceOfBeingErnest的答案。
自定义时间序列刻度标签的最佳方法是使用
如文档中所述,pandas使用matplotlib创建具有自己的自定义刻度格式的时间序列图:
pandas provides custom formatters for timeseries plots. These change the formatting of the axis labels for dates and times. By default, the custom formatters are applied only to plots created by pandas with DataFrame.plot() or Series.plot().
pandas时间序列图的刻度和标签当前默认为以下格式:
1 2 3 4 5 6 7 8 9 10 11 12 | import numpy as np # v 1.19.2 import pandas as pd # v 1.1.3 import matplotlib.dates as mdates # v 3.3.2 # Create random dataset stored as a pandas DataFrame with a DatetimeIndex rng = np.random.default_rng(seed=1) # random number generator date_day = pd.date_range(start='2015-07-01', end='2016-12-31', freq='D') traffic = rng.lognormal(sigma=2, size=date_day.size) df_day = pd.DataFrame(dict(traffic=traffic), index=date_day) # Create pandas plot with default settings except for figure size df_day.plot(figsize=(10,5)); |
为了能够使用mdates刻度定位器和格式化程序并覆盖默认的刻度格式,必须由matplotlib正确识别pandas的日期。问题在于,pandas和matplotlib具有不同的方法来计算用于在时间轴(默认为x轴)上定位刻度的日期数字。
在pandas中,时间是从
自2020年7月发布3.3.0版以来,Matplotlib使用与pandas相同的默认来源,但日期始终以天为单位编号:
Matplotlib represents dates using floating point numbers specifying the number of days since a default epoch of 1970-01-01 UTC; for example, 1970-01-01, 06:00 is the floating point number 0.25.
使用pandas时,可以通过运行
您可能已经猜到了,这意味着当时间序列的频率以天为单位时,就不需要日期转换,如此处所示,其中带有简单的自定义刻度定位器和格式化程序:
1 2 3 4 5 6 7 8 | ax = df_day.plot(figsize=(10,5)) # Create custom ticks using matplotlib date tick locator and formatter loc = mdates.MonthLocator(interval=2) ax.xaxis.set_major_locator(loc) fmt = mdates.DateFormatter('%b\ %Y') ax.xaxis.set_major_formatter(fmt) |
这种特殊情况便于将其他pandas的默认设置保持为x轴限制和较小的x刻度。但这是一般规则的例外。
要能够将mdates刻度定位器和格式化程序与任何频率类型的时间序列的pandas图一起使用,您需要使用(已存在但尚无文档字符串且几乎未记录的文档)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # Resample time series to monthly frequency and plot it using date # numbers that are compatible with mdates df_month = df_day.resample('MS').sum() ax = df_month.plot(figsize=(10,5), x_compat=True) # Set major and minor date tick locators maj_loc = mdates.MonthLocator(bymonth=np.arange(1,12,2)) ax.xaxis.set_major_locator(maj_loc) min_loc = mdates.MonthLocator() ax.xaxis.set_minor_locator(min_loc) # Set major date tick formatter zfmts = ['', '%b\ %Y', '%b', '%b-%d', '%H:%M', '%H:%M'] maj_fmt = mdates.ConciseDateFormatter(maj_loc, zero_formats=zfmts, show_offset=False) ax.xaxis.set_major_formatter(maj_fmt) ax.figure.autofmt_xdate(rotation=0, ha='center') ax.set_xlim(df_month.index.min(), df_month.index.max()); |
文档: