轴标签的 Matplotlib DateFormatter 不起作用
Posted
技术标签:
【中文标题】轴标签的 Matplotlib DateFormatter 不起作用【英文标题】:Matplotlib DateFormatter for axis label not working 【发布时间】:2016-02-18 00:35:17 【问题描述】:我正在尝试调整 x 轴日期刻度标签的格式,使其仅显示年份和月份值。从我在网上找到的内容来看,我必须使用mdates.DateFormatter
,但它在我当前的代码中根本没有生效。任何人都看到问题出在哪里? (日期是 pandas Dataframe 的索引)
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd
fig = plt.figure(figsize = (10,6))
ax = fig.add_subplot(111)
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
basicDF['some_column'].plot(ax=ax, kind='bar', rot=75)
ax.xaxis_date()
可重现的场景代码:
import numpy as np
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd
rng = pd.date_range('1/1/2014', periods=20, freq='m')
blah = pd.DataFrame(data = np.random.randn(len(rng)), index=rng)
fig = plt.figure(figsize = (10,6))
ax = fig.add_subplot(111)
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
blah.plot(ax=ax, kind='bar')
ax.xaxis_date()
仍然无法只显示年份和月份。
如果我在 .plot 之后设置格式,则会出现如下错误:
ValueError: DateFormatter 发现 x=0 的值,这是一个非法日期。这通常是因为您没有通知轴它正在绘制日期,例如使用 a
x.xaxis_date()
。
如果我把它放在 ax.xaxis_date() 之前或之后,都是一样的。
【问题讨论】:
我在这里找到了另一个很好的答案:***.com/questions/30133280/… 【参考方案1】:pandas 不能很好地处理自定义日期时间格式。
在这种情况下,您只需要使用原始 matplotlib。
import numpy
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas
N = 20
numpy.random.seed(N)
dates = pandas.date_range('1/1/2014', periods=N, freq='m')
df = pandas.DataFrame(
data=numpy.random.randn(N),
index=dates,
columns=['A']
)
fig, ax = plt.subplots(figsize=(10, 6))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
ax.bar(df.index, df['A'], width=25, align='center')
这给了我:
【讨论】:
2020年还是这样吗? @SimonKohlmeyer 我的示例是独立的。推荐你试一下,修改一下看看 对于发现这个的每个人:要测试这个,你必须添加fig.show()
,它仍然适用于 python 3.8.5 和 pandas 1.1.3【参考方案2】:
The accepted answer 声称“pandas 不适用于自定义日期时间格式”,但您可以利用 pandas 的 to_datetime()
函数在数据框中使用您现有的日期时间系列:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter
import pandas as pd
rng = pd.date_range('1/1/2014', periods=20, freq='m')
blah = pd.DataFrame(data = np.random.randn(len(rng)), index=pd.to_datetime(rng))
fig, ax = plt.subplots()
ax.xaxis.set_major_formatter(DateFormatter('%m-%Y'))
ax.bar(blah.index, blah[0], width=25, align='center')
将导致:
您可以看到不同的可用格式here。
【讨论】:
-1 因为两件事——pd.date_range
和pd.to_datetime
都返回DatetimeIndex
,所以pd.to_datetime(rng)
与rng
没有什么不同。除此之外,这个答案对接受的答案没有任何价值——您使用ax.bar
而不是df.plot(kind='bar')
的相同方法。【参考方案3】:
我遇到了同样的问题,我使用了一种解决方法将索引从日期时间格式转换为所需的字符串格式:
import numpy as np
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd
rng = pd.date_range('1/1/2014', periods=20, freq='m')
blah = pd.DataFrame(data = np.random.randn(len(rng)), index=rng)
fig = plt.figure(figsize = (10,6))
ax = fig.add_subplot(111)
# transform index to strings
blah_test = blah.copy()
str_index = []
for s_year,s_month in zip(blah.index.year.values,blah.index.month.values):
# build string accorind to format "%Y-%m"
string_day = '-:02d'.format(s_year,s_month)
str_index.append(string_day)
blah_test.index = str_index
blah_test.plot(ax=ax, kind='bar', rot=45)
plt.show()
结果如下图:
【讨论】:
【参考方案4】:仅使用 pandas 的解决方案
您可以使用DatetimeIndex
并利用时间戳的datetime properties 创建格式良好的报价。对于这种情况,matplotlib.dates
中的刻度定位器和格式化程序不是必需的,除非您在使用 matplotlib 的交互式界面进行放大和缩小时需要动态刻度(对于比本示例中更长的时间范围更相关)。
import numpy as np # v 1.19.2
import pandas as pd # v 1.1.3
# Create sample time series with month start frequency, plot it with a pandas bar chart
rng = np.random.default_rng(seed=1) # random number generator
dti = pd.date_range('1/1/2014', periods=20, freq='m')
df = pd.DataFrame(data=rng.normal(size=dti.size), index=dti)
ax = df.plot.bar(figsize=(10,4), legend=None)
# Set major ticks and tick labels
ax.set_xticks(range(df.index.size))
ax.set_xticklabels([ts.strftime('%b\n%Y') if ts.year != df.index[idx-1].year
else ts.strftime('%b') for idx, ts in enumerate(df.index)])
ax.figure.autofmt_xdate(rotation=0, ha='center');
【讨论】:
以上是关于轴标签的 Matplotlib DateFormatter 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
python使用matplotlib可视化为可视化图像的X轴和Y轴设置自定义的轴标签(axis labels of matplotlib plot)